16 电源管理(Power Management)
上一章
前一章讨论了 PCIe 端口或链路中出现的错误类型、检测方式、报告机制以及处理选项。由于 PCIe 设计为向后兼容 PCI 错误报告,因此本章将回顾 PCI 的错误处理方法作为背景信息。随后,我们将重点讨论 PCIe 对可纠正错误、非致命错误和致命错误的处理方式。
本章
本章为系统电源管理的讨论提供了整体背景,并详细描述了 PCIe 电源管理,该管理兼容 PCI 总线 PM 接口规范和高级配置与电源接口(ACPI)。PCIe 定义了 PCI-PM 规范的扩展,主要侧重于链路电源和事件管理。此外,还概述了 OnNow 倡议、ACPI 以及 Windows 操作系统的参与情况。
下一章
下一章详细介绍了 PCIe 功能生成中断的不同方式。传统的 PCI 模型使用引脚来实现此功能,但在串行模型中,边带信号并不理想,因此强制支持带内 MSI(消息信号中断)机制。为了支持使用 PCIe INTx 消息的传统系统,仍可模拟 PCI INTx# 引脚操作。本章将描述 PCI 传统 INTx# 方法以及较新版本的 MSI/MSI-X。
16.1 引言
PCI Express 电源管理(PM)定义了四个主要支持领域:
- 符合 PCI 标准的电源管理。PCIe 电源管理在硬件和软件层面均与 PCI-PM 及 ACPI 规范兼容。该支持要求所有功能包含 PCI 电源管理能力寄存器,使软件能够通过配置请求在软件控制下实现功能在电源管理状态间的转换。在 2.1 规范修订版中,通过引入动态功率分配(DPA)机制对此进行了改进——新增一组寄存器为 D0 电源状态添加了多个子状态,为软件提供更精细的电源管理机制。
- 原生 PCIe 扩展。这些扩展定义了链路自主的基于硬件的主动状态电源管理(ASPM),以及系统唤醒机制、用于报告电源管理事件(PME)的消息事务,以及计算和报告低功耗到主动状态延迟的方法。
- 带宽管理。2.1 规范修订版增加了硬件自动调整链路宽度或链路数据速率(或两者)以改善功耗的能力。这使得在需要时能够实现高性能,同时在可接受较低性能时保持低功耗。尽管带宽管理被视为电源管理主题,但我们在《链路初始化与训练》章节第 618 页的“动态带宽变更”部分中描述了这一能力,因为它涉及 LTSSM。
- 事件时序优化。外围设备在发起总线主控事件或中断时,若不考虑系统电源状态,会导致其他系统组件为了服务这些事件而保持在高功耗状态,从而造成不必要的更高功耗。这一缺陷在 2.1 规范中通过新增两种机制得到纠正:优化缓冲区刷新与填充(OBFF),允许系统告知外围设备当前的系统电源状态;以及延迟容忍度报告(LTR),允许设备报告其当前可容忍的服务延迟。
本章分为几个主要部分:
- 第一部分是关于电源管理的基础知识,涵盖系统软件在控制电源管理功能中的作用。本讨论仅从 Windows 操作系统的角度出发,因为它是 PC 中最常见的操作系统,其他操作系统不作描述。
- 第二部分“功能电源管理”(第 713 页)讨论如何使用 PCI-PM 能力寄存器将功能置于低功耗设备状态。请注意,部分寄存器定义已被 PCIe 功能修改或未使用。
- “主动状态电源管理(ASPM)”(第 735 页)描述基于硬件的自主链路电源管理。软件根据环境确定启用哪种 ASPM 级别,可能会读取该功能将引入的恢复延迟值;但电源状态转换的时机由硬件控制,软件不控制转换过程,也无法查看链路当前所处的电源状态。
- “软件发起的链路电源管理”(第 760 页)讨论当软件改变设备电源状态时强制执行的链路电源管理。
- “链路唤醒协议与 PME 生成”(第 768 页)描述设备如何请求软件将其恢复到活动状态,以便处理事件。当设备断电时,若设备需要监控事件并向系统发送唤醒信号,就必须提供辅助电源,以便恢复供电并重新激活链路。
- 最后介绍事件时序优化特性,包括 OBFF 和 LTR。
16.2 电源管理入门指南
PCI 总线 PM 接口规范描述了 PCIe 所需的电源管理寄存器。这些寄存器允许操作系统直接管理功能的电源环境。与其深入详细描述,不如先说明这一能力在系统整体架构中的定位。
16.2.1 PCI 电源管理基础
本节概述了 Windows 操作系统如何与其他主要软件和硬件组件交互,以管理单个设备及整个系统的电源使用情况。第 706 页的表格 16-1 介绍了此过程中涉及的主要元素,并提供了它们之间相互关系的基本描述。需要注意的是,PCI 电源管理规范和 ACPI 规范均未规定操作系统使用的电源管理策略。然而,它们确实定义了用于控制功能电源使用情况的寄存器(以及部分数据结构)。
表 16-1:PC 电源管理中涉及的主要软件/硬件元素
| 元素 | 职责 |
|---|---|
| OS | 通过向 ACPI 驱动程序、设备驱动程序和 PCI Express 总线驱动程序发送请求,直接管理整个系统的电源。具有节能意识的应用程序与操作系统交互,以实现设备电源管理。 |
| ACPI 驱动程序 | 管理不符合行业标准规范的嵌入式系统设备的配置、电源管理和热控制。例如芯片组专用寄存器、用于控制电源平面的系统板专用寄存器等。PCIe 功能(嵌入式或其他)中的 PM 寄存器由 PCI PM 规范定义,因此不由 ACPI 驱动程序管理,而是由 PCI Express 总线驱动程序管理(参见本表中的条目)。 |
| 设备驱动程序 | 类驱动程序可以与它被编写用于控制的任何设备类别一起工作。由于它并非针对特定供应商编写,因此不具备设备接口的位级知识;当需要向设备发出命令或检查设备状态时,它会向具体设备供应商提供的微型端口驱动程序发出请求。设备驱动程序也不了解特定总线实现中该设备类型的专有特性,例如
PCIe 功能的配置寄存器集;这些寄存器由 PCI Express
总线驱动程序负责访问。当它从操作系统收到控制 PCIe
设备电源状态的请求时,会将请求传递给 PCI Express
总线驱动程序。 - 当收到操作系统发出的设备掉电请求时,设备驱动程序会保存其关联功能的设备特定寄存器内容(即上下文保存),然后将请求传递给 PCI Express 总线驱动程序以更改设备电源状态。 - 当收到重新给设备上电的请求时,设备驱动程序将请求传递给 PCI Express 总线驱动程序以更改设备电源状态。PCI Express 总线驱动程序重新为设备供电后,设备驱动程序再将上下文恢复到该功能的设备特定寄存器中。 |
| 微型端口驱动程序 | 由设备供应商提供,它接收来自类驱动程序的请求,并将其转换为对设备寄存器组的正确访问序列。 |
表 16-1:PC 电源管理中涉及的主要软件/硬件要素(续)
| 要素 | 职责 |
|---|---|
| PCI Express 总线驱动程序 | 此驱动程序适用于所有符合 PCI Express
规范的设备。它负责管理设备的电源状态和配置寄存器,但不了解功能的设备特定寄存器集(这些知识由设备驱动程序用于访问设备寄存器集的微型端口驱动程序掌握)。它接收来自设备驱动程序的请求,以更改设备电源管理逻辑的状态。例如: - 当收到设备掉电请求时,该驱动程序负责保存功能的 PCI Express 配置寄存器上下文,然后禁用设备作为请求者发起事务或作为目标响应事务的能力,并写入功能的 PM 寄存器以更改其状态。 - 当设备需要重新上电时,PCI Express 总线驱动程序写入 PCI Express 功能的 PM 寄存器以更改其状态,然后将该功能的配置寄存器恢复到原始状态。 |
| 每个功能配置空间内的 PCI Express 电源管理寄存器。 | 这些寄存器的位置、格式和使用方式由 PCIe 规范定义。PCI Express 总线驱动程序理解该规范,因此当功能设备的驱动程序请求访问功能的电源管理寄存器时,总线驱动程序负责执行此操作。 |
| 系统主板电源平面与总线时钟控制逻辑 | 该逻辑的实现和控制通常取决于系统主板的具体设计,因此由 ACPI 驱动程序(在操作系统指导下)进行管理。 |
16.2.2 ACPI 规范定义了整体电源管理
ACPI(高级配置与电源接口)规范最初由多家公司于数年前联合制定,旨在为计算平台的 OSPM(操作系统级电源管理)提供行业标准。当时不同平台采用专有方式处理电源管理,导致供应商难以协调工作。此外,平台特定代码往往无法完全兼容操作系统运行,或未能全面感知系统状态及策略考量。ACPI 通过定义系统电源状态、硬件寄存器及软件交互机制,为基于操作系统的电源管理提供了解决方案。本书虽不深入探讨 ACPI 细节,但介绍其核心概念与术语将有所助益。
16.2.2.1 系统电源管理状态
第 708 页表 16-2 定义了系统整体在功耗方面的可能状态。其中“工作“、”睡眠“和“软关机“状态由 OnNow 设计倡议文档定义。
表 16-2:OnNow 设计倡议定义的系统电源管理状态
| 电源状态 | 描述 |
|---|---|
| 工作状态(G0/S0) | 系统完全正常运行。 |
| 睡眠状态(G1) | 系统看起来像是已关闭,功耗已降低。恢复到“工作”状态所需的时间与所选择的节能级别成反比。 - S1:缓存已刷新,CPU 暂停。 - S2:与 S1 相同,但 CPU 已断电;由于相较 S3 优势不大,因此并不常用。 - S3:也称为“挂起到内存”或“待机”。与 S2 类似,但系统上下文保存在内存中,且更多系统组件被关闭。系统唤醒时,CPU 开始完整启动流程,但会发现 CMOS 内存中的标志指示其从 RAM 重新加载上下文,因此程序执行可以很快恢复。 - S4:也称为“挂起到磁盘”或“休眠”。与 S3 类似,但系统会将系统上下文复制到磁盘,然后切断系统电源(包括主内存)。这能提供更好的节能效果,但重启时间更长,因为恢复程序执行前必须从磁盘恢复上下文。 |
| 软关机(G2/S5) | 系统似乎已关闭,功耗极低。由于内存内容已丢失,需要完全重启才能恢复到“工作“状态,但仍保留部分电力用于唤醒操作,例如按下系统上的“电源“按钮。 |
| 机械关闭 (G3) | 系统已断开所有电源连接,无可用电力。 |
16.2.2.2 设备电源管理状态
ACPI 还定义了设备级别的电源管理状态,这些状态列于第 709 页的表 16-3 中。第 709 页的表 16-3 以略有不同的形式呈现了相同的信息。支持这些设备状态的寄存器必须为 PCIe 设备实现。
表 16-3:设备级电源管理状态的 OnNow 定义
| 状态 | 描述 |
|---|---|
| D0 | 必需。设备完全运行,并从系统消耗全部功率。2.1 规范修订版新增了一组寄存器,用于支持 D0 下的 32 个子状态,这些寄存器被称为动态功率分配寄存器。 |
| D1 | 可选。一种低功耗状态,设备上下文可能会丢失也可能不会丢失。未给出此状态的具体定义,但它代表比 D0 更低、比 D2 更高的功耗状态。 |
| D2 | 可选。推测为比 D1 功耗更低的状态,可实现更大的节能效果,但会导致更长的恢复延迟,并可能使设备丢失部分上下文。 |
| D3 | 必需。设备已做好断电准备,无论电源是否实际关闭,上下文都可能丢失。恢复时间将比 D2 更长,但在此状态下可以优雅地切断设备电源。 |
16.2.2.3 设备上下文的定义
16.2.2.3.1 概述
在正常运行过程中,设备的工作状态会持续变化。设备驱动程序可能读写其寄存器,或设备上的本地处理器执行影响其与系统交互的代码。设备在特定时刻的状态包括:
- 其配置寄存器的内容。
- 其本地内存和 IO 寄存器的状态。
- 若设备包含处理器,则当前程序指针及其它寄存器的内容也包含在内。
此状态信息称为设备上下文。如果设备电源管理状态切换至更激进的节能级别,部分或全部上下文信息可能会丢失。若上下文信息未能保留,设备在返回 D0(完全运行)状态时将无法正常运行。
16.2.2.3.2 PME 上下文
若操作系统启用调制解调器通过来电唤醒系统后关闭电源,设备唤醒上下文需在此期间本地保留。芯片组会保留足够电力以监控此类事件。为支持此功能,PCIe 调制解调器必须实现包含以下内容的配置寄存器:
- PME 消息能力。
- PME 使能/禁用控制位。
- PME 状态位,指示设备是否已发送 PME 消息。
- 一个或多个设备特定的控制位,用于选择性启用或禁用可能导致设备发送 PME 消息的各种设备特定事件。
- 相应的设备特定状态位,指示设备发出 PME 消息的原因。
16.2.2.4 设备类别特定的 PM 规范
16.2.2.4.1 默认设备类别规范
如前所述,ACPI 定义了四种可能的设备电源状态(D0 至 D3)。同时,它还规定了所有设备类型必须实现的最低电源管理状态,具体内容见第 710 页的表 16-4。
表 16-4:默认设备类别电源管理状态
| 状态 | 描述 |
|---|---|
| D0 | 设备处于开启状态,以全功率运行,且功能完全正常。 |
| D1 | 此可选状态仅定义为功耗低于 D0,并不常用。 |
| D2 | 此可选状态仅定义为功耗低于 D1,并不常用。 |
| D3 | 设备消耗尽可能低的功耗,主电源可能被关闭。唯一的要求是,在电源仍接通的情况下,设备必须能够响应配置命令以重新进入 D0 状态。在此状态下,设备可以断电,当电源恢复时,设备将经历硬件复位。 |
16.2.2.4.2 设备类特定电源管理规范
除了默认设备类规范所要求的电源状态外,某些设备类可能需要中间电源状态(D1 和/或 D2),或在特定电源状态下表现出某些共同特性。
与特定设备类相关的规则可在微软硬件开发者网站上提供的设备类电源管理规范中找到。例如,以下设备类存在相应的设备类电源管理规范:
- 音频
- 通信
- 显示
- 输入
- 网络
- PC 卡
- 存储
16.2.2.5 电源管理策略所有者
设备的电源管理策略所有者定义为决定设备电源管理状态的软件模块。在 Windows 环境中,策略所有者是与该类设备关联的特定类别驱动程序。
16.2.3 PCI Express 电源管理与 ACPI 对比
16.2.3.1 PCI Express 总线驱动程序访问电源管理寄存器
如第 706 页表 16-1 和第 712 页图 16-1 所示,PCI Express 总线驱动程序了解电源管理配置寄存器的位置、格式及用法。当操作系统需要更改 PCIe 设备的电源状态,或确定其状态与功能时,便会调用该驱动程序。其他示例包括:
- IEEE 1394 总线驱动程序,该程序了解如何使用 1394 电源管理规范中定义的电源管理寄存器。
- USB 总线驱动程序,该程序了解如何使用 USB 电源管理规范中定义的电源管理寄存器。
16.2.3.2 ACPI 驱动程序控制非标准嵌入式设备
系统主板上嵌入了一些设备,其寄存器组并不遵循任何特定的行业标准规范。在启动时,BIOS 通过 ACPI 表(也称为命名空间)向操作系统报告这些设备。当操作系统需要与这些设备中的任何一个通信时,它会调用 ACPI 驱动程序,该驱动程序会执行一个与设备关联的、称为控制方法的处理程序。该处理程序同样位于 ACPI 表中,由平台设计者使用一种名为 ACPI 源语言(ASL)的特殊解释性语言编写。ASL 代码随后被编译成 ACPI 机器语言(AML)。请注意,AML 并非特定于处理器的机器语言,而是 ASL 源代码的标记化(即压缩)版本。ACPI 驱动程序包含一个 AML 令牌解释器,使其能够“执行”控制方法。
图 16-1:操作系统、设备驱动程序、总线驱动程序、PCI Express 寄存器与 ACPI 之间的关系
16.3 功能电源管理
PCI Express 功能必须支持电源管理,且需按如下所述实现若干寄存器及相关位域。
16.3.1 PM 能力寄存器集(The PM Capability Register Set)
PCI-PM 规范定义了电源管理能力配置寄存器。这些寄存器在 PCI 中为可选配置,但在 PCIe 中为强制要求,位于 PCI 兼容配置空间中,能力 ID 为 01h。软件可通过以下步骤定位这些寄存器:
- 功能配置状态寄存器的第 4 位应置位,表明功能配置报头第 13d 双字首字节中的能力指针有效。读取能力指针寄存器可获取功能能力寄存器链表中首个寄存器的偏移量。
- 如果该偏移量处双字的最低有效字节包含能力 ID 01h(参见第 713 页图 16-2),则此为 PM 寄存器集。紧随能力 ID 字节之后的字节是指向下一个能力字段的指针,该字段给出配置空间中下一个能力(如果存在)的偏移量。非零值为有效指针,而 00h 值表示链表结束。所有 PM 寄存器的描述可参见第 724 页的“PCI-PM 寄存器详细说明“。
图 16-2:PCI 电源管理能力寄存器集
| 31 1615 870 | ||||
|---|---|---|---|---|
| 电源管理能力(PMC) | 指向下一个能力的指针 | 能力 ID 01h | ||
| Data 寄存器 | 桥接支持扩展(PMCSR_BSE) | 控制/状态寄存器(PMCSR) | 第一个双字 第二个双字 |
16.3.2 设备电源管理状态(Device PM States)
每个 PCI Express 功能必须支持完全开启的 D0 状态和完全关闭的 D3 状态,而 D1 和 D2 为可选状态。以下章节描述了可能的电源管理状态。
16.3.2.1 D0 状态 - 完全开启(D0 State - Full On)
16.3.2.1.1 强制状态(Mandatory)
在此状态下,不启用任何电源节能措施,设备完全正常运行。所有 PCIe 功能必须支持 D0 状态,且技术上存在两个子状态:D0 未初始化与 D0 活动状态。当设备处于此状态时,ASPM 硬件控制可改变链路电源。第 714 页表 16-5 总结了 D0 状态下的电源管理策略。
16.3.2.1.2 D0 未初始化(D0 Uninitialized)
功能在基础复位后进入 D0 未初始化状态,或在某些情况下,当软件将其从 D3 转换至 D0 时进入该状态。通常,寄存器会恢复至默认状态。在此状态下,该功能呈现以下特征:
- 仅响应配置事务。
- 其命令寄存器启用位均恢复至默认状态,这意味着它无法发起事务,也无法作为内存或 IO 事务的目标。
16.3.2.1.3 D0 活动状态(D0 Active)
一旦功能通过软件配置并启用,即进入 D0 活动状态,并完全正常运行。
表 16-5:D0 电源管理策略
| 链路电源管理状态 | 功能电源管理状态 | 必须有效的寄存器或状态 | 电源 | 功能允许执行的操作 | 功能允许的操作 |
|---|---|---|---|---|---|
| L0 | D0 未初始化 | PME 上下文 ** | PCI Express 配置事务。 | 无 | |
| L0 L0s(必需)* L1(可选)* | D0 活动 | 全部 | 完整 | 任何 PCI Express 事务。 | 任何事务、中断或 PME。** |
| L2/L3 | D0 活动状态 | 不适用*** |
- 主动状态电源管理。 ** 如果此状态下支持 PME。 *** 不允许此总线/功能 PM 状态组合。
16.3.2.2 动态功率分配(DPA)(Dynamic Power Allocation)
可选。基础规范的 2.1 修订版新增了一项可选功能,定义了 D0 状态的 32 个额外子状态并描述了其特征。此举旨在促进设备驱动程序、操作系统与正在运行的应用程序之间关于电源管理的协商,部分原因在于某些功能没有能够良好处理电源管理的设备驱动程序。该模型的一个优势在于,设备在技术上仍保持在 D0 状态,因此可能能够以降低的能力继续运行,而无需像切换到 D1 或更低状态那样导致设备离线。
DPA 寄存器仅在设备电源状态为 D0 时适用,在 D1-D3 状态下不适用。最多可定义 32 个子状态,且必须从零到最大值连续编号。子状态 0 为初始默认值,代表该功能可消耗的最大功率。软件无需按顺序在子状态之间转换,也无需等待前一次转换完成后再请求更改子状态。因此,当某个功能完成子状态更改后,必须检查配置的子状态,若不匹配,则必须开始更改为配置值。支持 DPA 的寄存器位于增强配置空间中,如图 16-3(第 715 页)所示。
图 16-3:动态功率分配寄存器(Dynamic Power Allocation Registers)
| 偏移 | 寄存器 |
|---|---|
| 000h | PCIe 扩展能力头 |
| 004h | DPA 能力寄存器 |
| 008h | DPA 延迟指示寄存器 |
| 00Ch | DPA 控制寄存器 / DPA 状态寄存器 |
| 010h 至 02Ch | DPA 功率分配数组(大小由子状态数量决定) |
DPA 能力寄存器(如图 16-4 第 716 页所示)包含若干与子状态相关的关键数值。其中 Substate_Max 数值表示所描述的子状态数量,且这些编号必须从零开始连续递增至该数值。寄存器提供两个转换延迟值,每个子状态将通过延迟指示寄存器与其中一个值关联——该寄存器为每个可能的子状态分配一个比特位:若该位被置位则使用转换延迟值 1,否则使用值 0。延迟值表示从任意其他子状态转换至该子状态所需的最大时间。延迟值乘以转换延迟单位后,得到以毫秒为单位的时间。同样,功率分配比例值给出了每个子状态所用功率的乘数,单位为瓦特。对于每个定义的子状态,DPA 功率分配数组中的一个 32 位字段描述了该状态所使用的功率。第一个字段位于偏移量 010h 处,其余字段在后续的双字中实现。
图 16-4:DPA 能力寄存器(DPA Capability Register)
DPA Control 寄存器的低 5 位由软件写入,用于设置新的子状态;当前子状态则可以从 Status 寄存器中读取,如第 716 页图 16-5 所示。需要注意的是,Status 寄存器的 bit 8 用于指示是否已经启用了 DPA 子状态,但该位的属性标注为 RW1C(Read, Write 1 to Clear,读/写 1 清零)。这意味着软件可以通过向该位写入 1 来清除它,但不能通过写入来将其置位。复位后,DPA 默认处于启用状态。如果软件不打算使用 DPA,就需要向该位写入 1,从而将其禁用。
图 16-5:DPA 状态寄存器
16.3.2.3 D1 状态 - 轻度睡眠(D1 State—Light Sleep)
可选。在进入此状态前,软件必须确保所有未完成的非发布请求均已收到相应的完成通知。可通过轮询 PCI Express 能力块中设备状态寄存器的待处理事务位来实现;当该位清零时,即可安全继续。在此轻度节能状态下,除非启用 PME 消息,否则功能将不会发起请求。D1 状态的其他特性包括:
- 当设备进入 D1 状态时,链路被强制进入 L1 电源状态。
- 在此状态下,配置请求和消息请求可被接受,但所有其他请求必须作为不支持的请求处理,所有完成操作可选择作为意外完成处理。
- 如果传入请求导致错误且错误报告功能已启用,则在此状态下可发送错误消息。如果发生其他类型的错误(例如完成超时),则消息将不会发送,直到设备恢复到 D0 状态。
- 功能可重新激活链路并发送 PME 消息(如果在此状态下支持并启用该功能),以通知软件功能已发生需要恢复供电的事件。
- 在此状态下,功能可能会或可能不会丢失其上下文。如果确实丢失且设备支持 PME,则在此状态下至少必须维持其 PME 上下文(参见第 710 页的“PME 上下文”)。
- 功能必须恢复到 D0 活动电源管理状态才能完全正常运行。
表 16-6 列出了 D1 状态下的电源管理策略。
表 16-6:D1 电源管理策略
| 链路 PM 状态 | 功能 PM 状态 | 必须有效的寄存器或状态 | 电源 | 允许对功能执行的操作 | 功能允许执行的操作 |
|---|---|---|---|---|---|
| L1 | D1 | 设备类特定寄存器和 PME 上下文。* | ≤ D0 未初始化 | 配置请求与消息。链路需回退至 L0 以处理该请求。 | PME 消息。** 尽管通常不被允许,但此类消息将要求链路回退至 L0。 |
| L2-L3 | D1 | 不适用 * | 不适用 * | 不适用 * | 不适用 * |
* 此总线/功能 PM 状态组合不被允许。 ** 如果在此状态下支持 PME。
16.3.2.4 D2 状态 - 深度睡眠(D2 State—Deep Sleep)
可选。在进入此状态之前,软件必须确保所有未完成的非发布请求均已收到其关联的完成通知。这可以通过轮询设备状态寄存器中的待处理事务位来实现。 PCI Express 能力块;当该位清零时,即可安全继续操作。此电源状态比 D1 提供更深的节能效果,但低于 D3 状态。与 D1 类似,该功能不会发起请求(PME 消息除外),也不会作为除配置外其他请求的目标。在此状态下,软件仍必须能够访问该功能的配置寄存器。
D2 状态的其他特性包括:
- 在进入此状态之前,软件必须确保所有未完成的非发布请求均已收到其关联的完成通知。这可以通过轮询 PCIe 能力块中设备状态寄存器的“待处理事务“位来实现。在某些情况下,完成通知可能永远不会返回,此时软件应等待足够长的时间以确保这些完成通知确实不会返回。
- 当设备转换至 D2 状态时,链路状态必须同步转换至 L1 状态。
- 在此状态下,配置请求和消息请求可被正常接收,但所有其他请求必须作为“不支持请求“处理,而所有完成通知可选择性地作为“意外完成“处理。
- 如果传入的请求导致错误且已启用错误报告功能,则在此状态下可能会发送一条错误消息。如果发生其他类型的错误(例如完成超时),则消息将不会发送,直到设备恢复到 D0 状态。
- 如果支持并已启用,功能可能会发送一条 PME 消息,以通知软件需要恢复供电来处理某个事件。
- 在此状态下,功能可能会丢失其上下文,也可能不会。如果丢失上下文且设备支持 PME 消息,则它必须至少为此目的维护其 PME 上下文。
- 功能必须返回到 D0 活动状态才能完全正常运行。
第 719 页的表 16-7 展示了 D2 状态下的电源管理策略。
表 16-7:D2 电源管理策略
| 链路电源管理状态 | 功能 PM 状态 | 必须有效的寄存器和/或状态 | 电源 | 允许对功能执行的操作 | 功能允许的操作 |
|---|---|---|---|---|---|
| L1 | D2 | 设备类特定的寄存器和 PME 上下文。* | ≤ 下一个更高支持的 PM 状态或 D0 未初始化。 | 设备类允许的配置请求和事务(通常无)。这要求链路转换回 L0 状态。 | PME 消息。* 虽然通常不允许,但它们需要链路回退到 L0。 |
| L2/L3 | D2 | 不适用** | 不适用** | 不适用** | 不适用** |
* 如果在此状态下支持 PME。 ** 不允许的总线/功能 PM 状态组合。
16.3.2.5 D3 - 完全关闭(D3—Full Off)
必需。所有功能必须支持 D3 状态。这是最深度的状态,节能效果最大化。当软件向设备写入此电源状态时,设备进入 D3hot 状态,表示电源仍然接通。如果存在辅助电源(Vaux),则从设备移除电源(Vcc)会使其进入 D3cold 状态,链路进入 L2;若无辅助电源,则进入 L3 状态。
16.3.2.5.1 D3hot 状态(必选)
软件通过将适当的值写入其电源管理控制与状态寄存器(PMCSR)的 PowerState 字段,将功能置于 D3hot 状态。在此状态下,该功能只能发起 PME 或 PME_TO_ACK 消息,且仅能响应配置请求或 PME_Turn_Off 消息。当设备处于 D3hot 状态时,软件必须能够访问该功能的配置寄存器,至少应能将其状态更改回 D0。D3hot 的其他特性包括:
在进入此状态前,软件必须确保所有非发布的未处理请求均已收到对应的完成响应。可通过轮询 PCIe 能力块设备状态寄存器中的“待处理事务“位来实现。若完成响应可能永远不会返回,软件应等待足够长的时间以确保其确实不会返回。
当功能设备切换至 D3hot 状态时,链路被强制进入 L1 状态。
功能设备允许发送 PME 消息,通知电源管理软件需要恢复至完全活动状态(前提是该设备支持在 D3hot 状态下生成 PM 事件,且已启用此功能)。
进入该状态时,功能上下文可能会丢失,若电源关闭,规范假定所有上下文都将丢失。另一方面,若在软件启动返回 D0 状态前电源从未关闭,则上下文可得以保持。在早期规范版本中,这是不可能的;从 D3hot 状态切换至 D0 状态涉及软复位,所有寄存器将被重新初始化。然而,该规范的 1.2 修订版新增了一个名为“无软复位“的能力位,用于指示该功能在此情况下不会执行软复位。为了在 D3hot 状态中生成 PME 消息,设备必须维持其 PME 上下文(参见第 710 页的“PME 上下文“)。
功能在以下两种情况下退出 D3hot 状态:
- 若 Vcc 从设备移除,则其从 D3hot 状态转换至 D3cold 状态。
- 软件可向功能 PMCSR 寄存器的 PowerState 字段写入数据,将其 PM 状态更改为 D0。当编程设定为退出 D3hot 并返回 D0 时,功能将返回至 D0 未初始化 PM 状态。复位操作可能执行也可能不执行。第 721 页的表 16-8 列出了 D3hot 状态下的 PM 策略。
表 16-8:D3hot 电源管理策略
| 总线电源管理状态 | 功能电源管理状态 | 必须有效的寄存器和/或状态 | 电源 | 功能允许执行的操作 | 功能允许的操作 |
|---|---|---|---|---|---|
| L1 | D3hot | PME 上下文。** | 下一个支持的更高 PM 状态或 D0 未初始化。 | PCI Express 配置事务和 PME_Turn_Off 广播消息***(这些只能在链路转换回 L0 状态后发生。) | PME 消息** PME_TO_ACK 消息*** PM_Enter_L23 DLLP***(这些仅在链路返回 L0 后才可能发生) |
| L2/L3 就绪 | D3hot | L2/L3 就绪状态在遵循 PME_Turn_Off 握手序列后进入,该序列为设备移除电源做好准备*** | |||
| L2/L3 | D3hot | 不适用* | 不适用* | 不适用* | 不适用* |
* 不允许此总线/功能 PM 状态组合。 ** 如果在此状态下支持 PME。 *** 有关该序列的详细信息,请参见第 764 页的“L2/L3 就绪握手序列”。
16.3.2.5.2 D3cold 状态(必选)
- 每个 PCI Express 功能在移除电源(Vcc)后进入 D3cold PM 状态。当电源恢复时,设备必须复位或产生内部复位,从 D3cold 状态转换到 D0 未初始化状态。能够生成 PME 的功能必须在此状态下以及转换到 D0 状态时保持 PME 上下文。由于进入此状态时电源已被移除,功能若要维持 PME 上下文,必须配备辅助电源。然后,当设备进入 D0 未初始化状态时,如果具备相应能力且已启用,它可以生成 PME 消息以通知系统唤醒事件。有关辅助电源的更多信息,请参阅第 775 页的“辅助电源”。
第 722 页的表 16-9 展示了 D3cold 状态下的 PM 策略。
表 16-9:D3cold 电源管理策略
| 总线 PM 状态 | 功能 PM 状态 | 必须有效的寄存器和/或状态 | 电源 | 允许对功能执行的操作 | 功能允许的操作 |
|---|---|---|---|---|---|
| L2 | D3cold | PME 上下文* | 辅助电源 | 仅总线复位 | 信号信标或 WAKE#** |
| L3 | D3cold | 无 | 无 | 仅总线复位 | 无 |
* 如果在此状态下支持 PME。 ** 用于唤醒以恢复时钟和电源的信号方法取决于具体的外形规格。
16.3.2.6 功能 PM 状态转换
图 16-6 展示了 PCIe 功能的状态转换。第 723 页的表 16-10 描述了每种转换。第 724 页的表 16-11 从硬件和软件两个角度说明了状态之间的转换。
图 16-6:PCIe 功能 D 状态转换
表 16-10:功能状态转换说明
| 从状态 | 待定 | 描述 |
|---|---|---|
| D0 未初始化 | D0 活动 | 该功能已由驱动程序完全配置并启用。 |
| D0 活动状态 | D1 | 软件将 PMCSR PowerState 写入 D1。 |
| D2 | 软件将 PMCSR PowerState 写入 D2。 | |
| D3hot | 软件将 PMCSR PowerState 写入 D3hot。 | |
| D1 | D0 活动状态 | 软件将 PMCSR PowerState 写入为 D0。 |
| D2 | 软件将 PMCSR PowerState 写入为 D2。 | |
| D3hot | 软件将 PMCSR PowerState 写入为 D3hot。 | |
| D2 | D0 活动状态 | 软件将 PMCSR PowerState 写入 D0。 |
| D3hot | 软件将 PMCSR PowerState 写入 D3hot。 | |
| D3hot | D3cold | 功能已断电。 |
| D0 未初始化 | 软件将 PMCSR 电源状态写入 D0。 | |
| D3cold | D0 未初始化 | 功能恢复供电。 |
表 16-11:功能状态转换延迟
| 初始状态 | 下一状态 | 软件保证的最小延迟 |
|---|---|---|
| D0 | D1 | 0 |
| D0 或 D1 | D2 | 从新状态设置到首次访问需 200 微秒(包括配置访问) |
| D0、D1 或 D2 | D3hot | 从新状态设置到首次访问需 10 毫秒。 |
| D1 | D0 | 0 |
| D2 | D0 | 从新状态设置到首次访问。 |
| D3hot | D0 | 从新状态设置到首次访问需 10 毫秒。 |
| D3cold | D0 |
16.3.3 PCI-PM 寄存器详细描述(Detailed Description of PCI-PM Registers)
PCI 总线 PM 接口规范定义了 PCIe 功能中实现的 PM 寄存器(见图 16-7)。配置软件可以确定 PM 能力并控制其属性。
图 16-7:PCI 功能的 PM 寄存器
16.3.3.1 电源管理能力(PMC)寄存器(PM Capabilities (PMC) Register)
该 16 位只读寄存器的字段描述见表 16-12。
表 16-12:PMC 寄存器位分配
| 位(比特) | 描述 |
|---|---|
| 31:27 | PME_Support 字段。指示该功能在哪些 PM 状态下能够发送 PME
消息。某位为 0 表示相应 PM 状态不支持 PME 通知。 位对应 PM 状态: 27 对应 D0, 28 对应 D1, 29 对应 D2, 30 对应 D3hot , 31 对应 D3cold(该功能需要辅助电源支持 PME 逻辑及通过信标或 WAKE# 引脚进行唤醒信号传输)。支持从 D3cold 唤醒的系统必须同时支持辅助电源,并利用该电源发出唤醒信号。 对于在根端口和交换端口内实现的虚拟 PCI-PCI 桥,位 31、30 和 27 必须设置为 1b。这是转发 PME 消息的端口所必需的要求。 |
| 26 | D2_Support 位。1 = 功能支持 D2 电源管理状态。 |
| 25 | D1_Support 位。1 = 功能支持 D1 电源管理状态。 |
表 16-12:PMC 寄存器位分配(续)
| 位(比特) | 描述 |
|---|---|
| 24:22 | Aux_Current 字段。对于支持从 D3cold 状态生成 PME
消息的功能,该字段报告该功能中保留 PME 上下文信息的逻辑对
3.3Vaux 电源的当前需求(参见第 775
页的“辅助电源”)。软件利用此信息确定可同时启用 PME
生成的功能数量(基于每个功能从系统 3.3Vaux
电源汲取的总电流以及电源的供电能力)。 - 如果该功能不支持从 D3cold PM 状态进行 PME 通知,则此字段未实现,读取时始终返回零。或者,PCI Express 定义的新特性允许不支持 PME 的设备报告在设备控制寄存器中的 Aux Power PM Enable 位启用时所汲取的辅助电流量。 - 如果该功能实现了 Data 寄存器(参见第 731 页的“Data 寄存器”),则读取此字段时始终返回零。在报告该功能的 3.3Vaux 电流需求时,Data 寄存器优先于此字段。 - 如果该功能支持来自 D3cold 状态的 PME 通知,且未实现 Data 寄存器,则 Aux_Current 字段报告该功能所需的 3.3Vaux 电流。其编码方式如下: Bit 24 23 22 Max Current Required 1 1 1 375mA 1 1 0 320mA 1 0 1 270mA 1 0 0 220mA 0 1 1 160mA 0 1 0 100mA 0 0 1 55mA 0 0 0 0mA |
表 16-12:PMC 寄存器位分配(续)
| 位(比特) | 描述 |
|---|---|
| 21 | 设备特定初始化(DSI)位。该位为 1 表示在进入 D0 未初始化状态后,该功能需要在其 PCI 配置头寄存器设置之外进行额外配置,类驱动程序才能使用该功能。Microsoft 操作系统不使用此位。相反,确定和初始化由类驱动程序完成。 |
| 20 | 保留位。 |
| 19 | PME_Clock 位。不适用于 PCI Express。必须硬连线为 0。 |
| 18:16 | 版本字段。该字段表示该功能所遵循的 PCI 总线 PM
接口规范的版本。 Bit 18 17 16 Complies with Spec Version 0 0 1 1.0 0 1 0 1.1 (required by PCI Express) |
16.3.3.2 PM 控制与状态寄存器(PMCSR)(PM Control and Status Register)
该寄存器是所有 PCI Express 设备所必需的,其用途如下所述。第 728 页的表 16-13 提供了 PMCSR 位字段的描述。
- 如果该功能实现了 PME 能力,则 PME 使能位允许软件启用或禁用该功能断言 PME 消息或 WAKE# 信号的能力,同时状态位反映是否发生了 PME 事件。
- 如果实现了可选的 Data 寄存器(参见第 731 页的“Data 寄存器”),则使用两个字段来允许软件选择可通过 Data 寄存器读取的信息,并为 Data 寄存器值提供缩放倍数。
- 寄存器的电源状态字段可被读取以确定该功能的当前 PM 状态,也可通过写入将该功能置于新的 PM 状态。
表 16-13:PM 控制/状态寄存器(PMCSR)位分配
| 位(比特) | 复位时的值 | 读/写 | 描述 |
|---|---|---|---|
| 31:24 | 全零 | 只读 | 参见第 731 页的“Data 寄存器”。 |
| 23 | 零 | 只读 | 在 PCI Express 中未使用 |
| 22 | 零 | 只读 | PCI Express 中未使用 |
| 21:16 | 全零 | 只读 | 保留 |
| 15 | 请参阅描述。 | 读取,写入 1 以清除,粘性 RW1CS | PME_Status 位。可选:仅当功能支持 PME
通知时实现,否则为零。该位反映功能是否经历过
PME(即使此寄存器中的 PME_En 位已禁用功能发送 PME
消息的能力)。如果设置为 1,则表示功能经历过 PME。软件通过写入 1
来清除此位。 复位后,如果功能在 D3cold 状态下不支持 PME,则此位为零。如果功能在 D3cold 状态下支持 PME,则此位在初始操作系统启动时不确定,但之后反映功能是否经历过 PME。 如果功能支持从 D3cold 状态唤醒的 PME,则此位的状态必须在断电或功能复位时保持不变(粘性位)。这意味着辅助电源在这些条件下保持此逻辑处于活动状态(参见第 775 页的“辅助电源“)。 |
表 16-13:PM 控制/状态寄存器(PMCSR)位分配(续)
| 位(比特) | 复位值 | 读/写 | 描述 |
|---|---|---|---|
| 14:13 | 设备特定 | 只读 | Data_Scale 字段。可选。如果该功能未实现 Data 寄存器,则该字段硬连线返回零。如果实现了 Data 寄存器,则 Data_Scale 字段为必填项,且必须为只读值,表示其乘数。Data_Scale 字段的值及其解释取决于通过 Data_Select 字段选择在 Data 寄存器中查看的数据项。 |
| 12:9 | 0000b | 读/写 | Data_Select 字段。可选。如果该功能未实现 Data 寄存器,则此字段硬连线返回零。如果实现了 Data 寄存器,则 Data_Select 为强制性的读/写字段。写入此寄存器的值用于选择要在 Data 寄存器中查看的数据。该值必须乘以从 Data_Scale 字段读取的值。 |
表 16-13:PM 控制/状态寄存器 (PMCSR) 位分配(续)
| 位(比特) | 复位值 | 读/写 | 描述 |
|---|---|---|---|
| 8 | 参见描述。 | 读/写 | PME_En 位。可选。 1 = 启用功能在事件发生时发送 PME 消息的能力; 0 = 禁用。 如果该功能不支持从任何电源状态生成 PME,则读取时该位始终返回零。 复位后,如果该功能不支持从 D3cold 状态生成 PME,则该位为零。如果该功能支持从 D3cold 状态生成 PME: - 在初始操作系统启动时,该位不确定。 - 否则,它启用或禁用该功能在 PME 发生时发送 PME 消息的能力。 如果该功能支持从 D3cold 状态生成 PME,则该位的状态必须在该功能保持 D3cold 状态期间,以及从 D3cold 转换到 D0 未初始化状态期间保持不变。这意味着 PME 逻辑必须使用辅助电源在这些条件下为此逻辑供电。 |
| 7:2 | 全零 | 只读 | 保留 |
| 1:0 | 00b | 读/写 | PowerState
字段。必填。软件使用此字段读取功能的当前电源管理状态,或写入新的电源管理状态。如果软件选择了功能不支持的电源管理状态,写入操作将正常完成,但数据会被丢弃,且不会发生状态变更。
10 PM 状态 00 D0 01 D1 10 D2 11 D3hot |
16.3.3.3 Data 寄存器(Data Register)
可选,只读。请参考第 732 页的图 16-8。Data 寄存器是一个 8 位只读寄存器,为软件提供以下信息:
- 所选 PM 状态下消耗的功率;在功率预算中很有用。
- 所选 PM 状态下耗散的功率;在管理热环境时很有用。
- 任何类型的数据都可以通过此寄存器报告,但 PCI-PM 规范仅为其定义了功耗和功率耗散信息。
如果实现了 Data 寄存器,则必须同时实现 PMCSR 寄存器的 Data_Select 和 Data_Scale 字段,且不得实现 PMC 寄存器的 Aux_Current 字段。
16.3.3.3.1 确定 Data 寄存器的存在
软件可执行以下步骤来检查 Data 寄存器的存在:
- 将值 0000b 写入 PMCSR 寄存器的 Data_Select 字段。
- 从 Data 寄存器或 PMCSR 寄存器的 Data_Scale 字段读取数据。若读取到非零值,则表示 Data 寄存器以及 PMCSR 寄存器的 Data_Scale 和 Data_Select 字段均已实现。若读取到零值,则转至步骤 4。
- 如果 Data_Select 字段的当前值不是 1111b,则转至步骤 4。如果 Data_Select 字段的当前值为 1111b,则所有可能的 Data 寄存器值均已扫描并返回零,表明 Data 寄存器以及 PMCSR 寄存器的 Data_Scale 和 Data_Select 字段均未实现。
- 递增 Data_Select 字段的内容,然后返回步骤 2。由于 Data_Select 字段仅有 4 位,完整扫描需要测试 16 种可能的选择值,并观察 Data 寄存器和缩放寄存器中是否出现非零值。
16.3.3.3.2 Data 寄存器的操作
返回的信息通常是该功能在不同电源管理状态(如设备数据手册所列)下最差情况功耗和散热特性的静态副本。要使用 Data 寄存器,程序员需遵循以下步骤:
- 向 PMCSR 寄存器的 Data_Select 字段(参见第 733 页表 16-14)写入一个值,以选择通过 Data 寄存器查看的数据项。
- 从 Data 寄存器读取数据值,并从 PMCSR 寄存器的 Data_Scale 字段读取缩放值。
- 将数值乘以缩放因子。
16.3.3.3.3 多功能设备(Multi‐Function Devices)
在多功能 PCI Express 设备中,每个功能必须提供自身的电源信息。所有功能共用的逻辑部分的电源信息通过功能零的 Data 寄存器报告(参见第 733 页表 16-14 中的 Data_Select 值 )。
16.3.3.3.4 虚拟 PCI 到 PCI 桥电源数据(Virtual PCI‐to‐PCI Bridge Power Data)
规范未指定根复合体或交换机中 PCI 到 PCI 桥功能的数据库使用方式。但为保持 PCI-PM 兼容性,桥必须报告其消耗的电源信息。软件可读取交换机每个端口的虚拟 PPB Data 寄存器,以确定交换机在各电源状态下的功耗。
图 16-8:PM 寄存器
表 16-14:Data 寄存器解读
| Data_Select 值 | Data 寄存器中报告的数据 | PMCSR 中 Data_Scale 字段的解读 | 单位/精度 |
|---|---|---|---|
| 00h | D0 消耗的功率 | 00b = 未知; 01b = 乘以 0.1; 10b = 乘以 0.01; 11b = 乘以 0.001 |
Watts |
| 01h | D1 消耗的功率 | 同上 | 同上 |
| 02h | D2 消耗的功率 | 同上 | 同上 |
| 03h | D3 中消耗的功率 | 同上 | 同上 |
| 04h | D0 中耗散的功率 | 同上 | 同上 |
| 05h | D1 耗散的功率 | 同上 | 同上 |
| 06h | D2 耗散的功率 | 同上 | 同上 |
| 07h | D3 耗散的功率 | 同上 | 同上 |
| 08h | 在多功能 PCI 设备中,功能 0 表示封装内所有功能共用的逻辑所消耗的功率。 | 同上 | 同上 |
| 09h-0Fh | 保留供多功能设备中功能 0 的未来使用。 | 保留 | TBD |
| 08h-0Fh | 在单功能设备以及多功能设备中除功能 0 以外的其他功能中保留。 | 保留 | TBD |
16.4 链路电源管理简介(Introduction to Link Power Management)
我们刚刚了解了软件如何将设备置于多种设备电源状态之一,现在来看看 PCIe 如何管理链路电源。设备电源与链路电源相互关联,如第 734 页表 16-15 所示。还需注意下游设备与上游设备之间的关系,可概括为:上游设备或链路不能处于比其下游设备更激进的节能状态。原因在于 需要确保端点设备的数据包能够及时传输——若上游设备处于更低功耗状态,其流量传输将出现延迟。每种关系描述如下:
D0 - 设备处于完全供电状态,通常处于 L0 链路状态。在不脱离此状态的前提下,可通过使用 DPA 子状态(参见第 714 页“动态电源分配(DPA)“)以及基于硬件的链路电源管理(详见第 735 页“主动状态电源管理(ASPM)”)实现一定程度的节能。
D1 与 D2 - 当软件将设备状态更改为 D1 或 D2 时,链路必须自动转换至 L1 状态。由于此操作涉及链路双方,因此存在一种握手机制,以确保操作有序进行。
D3hot - 当软件将设备置于 D3 状态时,链路会自动转换至 L1 状态,这与进入 D1 和 D2 状态时的情况相同。此时,软件可选择移除参考时钟和电源,使设备进入 D3cold 状态。但在执行此操作前,系统应启动握手流程,通过将链路置于 L2/L3 就绪状态来做好准备工作。 D3cold - 在此状态下,主电源和参考时钟已关闭。然而,辅助电源(Vaux)可能仍可用,使设备能够向系统发送唤醒事件信号。若 Vaux 可用,链路状态将处于 L2;若主电源已移除且 Vaux 不可用,链路将处于 L3。第 735 页的表 16-16 提供了关于链路电源状态的更多信息。
表 16-15:设备与链路电源状态之间的关系
| 下游组件 D 状态 | 允许的上游组件 D 状态 | 允许的互连状态 |
|---|---|---|
| D0 | D0 | L0、L0s 和 L1(可选) |
| D1 | D0-D1 | L1 |
| D2 | D0-D2 | L1 |
| D3hot | D0-D3hot | L1、L2/L3 就绪 |
| D3cold | D0-D3cold | L2(辅助电源),L3 |
表 16-16:链路电源状态特性
| 状态 | 描述 | 软件定向? | ASPM | 参考时钟 | 主电源 | PLL | Vaux |
|---|---|---|---|---|---|---|---|
| L0 | 完全激活 | 是 (D0) | 在 | 开启 | 开启 | 在 | 开/关 |
| L0s | 待机 | 无 | 是 (D0) | 开启 | 开启 | 开启 | 开/关 |
| L1 | 低功耗待机 | 是*(D1-D3hot) | 是(可选)(D0) | 开启 | 开启 | 开启/关闭 | 开启/关闭 |
| L2/L3 就绪 | 断电暂存 | 是 PME_Turn_Off 握手 | 否 | 开启 | 开启 | 开启/关闭 | 开启/关闭 |
| L2 | 低功耗睡眠 | 是** | 否 | 关闭 | 关闭 | 关闭 | 开启 |
| L3 | 关闭(零功耗) | 不适用 | 不适用 | 关闭 | 关闭 | 关闭 | 关闭 |
* L1 状态可通过电源管理软件将设备置于 D1、D2 或 D3 状态进入,也可在 ASPM 机制下通过硬件控制进入。 ** 规范将 L2 状态描述为软件控制状态。表中其他 L 状态均被列为软件控制状态,因为软件负责启动进入这些状态的转换。例如,当软件启动设备电源状态变更至 D1、D2 或 D3 时,设备必须通过进入 L1 状态来响应。随后,软件通过发送 PME_Turn_Off 消息触发向 L2/L3 就绪状态的转换。最后,在设备完成向 L2/L3 就绪状态转换后,软件启动设备断电操作。由于 L2 状态下仍保留 Vaux 辅助电源,因此可通过唤醒事件通知软件。
16.5 主动状态电源管理(ASPM)(Active State Power Management)
ASPM 是一种基于硬件的链路电源节能机制,仅在设备处于 D0 设备电源状态时生效。进入和退出 ASPM 状态的过程由硬件根据具体实现标准自动触发;软件无法控制或监控此操作,只能通过配置寄存器位启用或禁用该功能(参见第 744 页图 16-15)。
ASPM 定义了两种低功耗状态:
- L0s(待机状态)——该状态可显著降低功耗,同时仍保持较短的进入和退出延迟。其主要实现方式是将发送器置于电气空闲状态。在早期版本的 PCIe 规范中,所有设备都必须支持此状态,但在 3.0 规范中已改为可选功能。
- L1 ASPM - L1 的目标是在允许较长进入和退出延迟的情况下,实现比 L0s 更高的功耗节省。例如,在此状态下,两个发送器同时进入电气空闲状态。与早期规范一样,3.0 规范中对此状态的支持仍然是可选的。
16.5.1 电气空闲(Electrical Idle)
将发送器置于电气空闲状态是 ASPM 的核心部分,因此讨论其工作原理将有助于理解。当发送器的差分信号(TxD+和 TxD-)进入电气空闲状态时,它会停止信号传输,并将电压保持在非常接近共模电压的水平,差分电压为 0V。信号转换会消耗功率,因此在链路上停止信号转换可以节省功耗,同时仍允许相对快速地恢复到正常的链路活动状态,此时链路被称为处于 L0 状态。根据功耗节省的程度,链路处于 L0s 或 L1 状态。在此期间,发送器可以选择保持低阻抗状态,或通过关闭其端接逻辑切换至高阻抗状态以进一步节省功耗。除了 L0s 和 L1 状态外,当链路被禁用时,电气空闲状态也会生效。
16.5.1.1 发送器进入电气空闲状态(Transmitter Entry to Electrical Idle)
希望进入电气空闲状态的发送器必须首先通知链路伙伴,以免后续信号中断被误判为错误。它们通过发送 EIOS(电气空闲有序集)来实现这一目的,随后迅速停止传输并将链路输出驱动器置于三态。EIOS 的具体形式取决于所使用的编码方式,具体内容将在后续章节中描述。发送完最后一个 EIOS 后,发送器必须在 8 ns 内进入电气空闲状态,并在此模式下保持至少 20 ns,无论数据速率如何。电气空闲期间允许的差分峰值电压必须在 0 至 20 mV 之间(同样与数据速率无关),以降低接收器将线路噪声误判为有效信号的可能性。(有关这些时序和电压参数的更多信息,请参见第 489 页的表 13-3。)
Gen1/Gen2 模式编码。对于 Gen1/Gen2 模式,EIOS 的形式如图 16-9(第 737 页)所示。必须发送全部四个符号,但接收器只需看到两个 IDL 控制字符即可识别此状态。
图 16-9:Gen1/Gen2 模式 EIOS 模式
Gen3 模式编码。对于 Gen3 模式,EIOS 是一个有序集块,由有序集同步头(01b)后接 16 个全为 66h 的字节组成,如图 16-10(第 737 页)所示。有趣的是,若发送器将直接进入电气空闲状态,则无需完成该数据块,但允许在符号 13 之后(符号 14 或 15 中的任意位置)停止。其原因是为了适应 128b/130b 编码下内部时钟与符号边界不对齐的情况。这种截断不会在接收器端引发问题,因为接收器仅需识别 EIOS 的符号 0-3 即可。
图 16-10:Gen3 模式 EIOS 模式
16.5.1.2 发送器退出电气空闲状态(Transmitter Exit from Electrical Idle)
当发送器被指示退出电气空闲状态时,其执行步骤取决于当前使用的数据速率(见下文)。但必须在 8 ns 内通过发送 FTS 或 TS1/TS2 序列恢复传输,从而切换回 L0 全开状态。
Gen1 模式。对于 2.5 GT/s,其过程较为简单:首先使用有效的差分信号发送 TS1 或 FTS,以告知接收器状态变化。接收器检测到电压高于静噪阈值后,开始评估传入信号。
Gen2 模式。当使用 5.0 GT/s 时,信号变化速度极快,以至于无法达到较高的电压水平。这使得快速检测电压是否恢复至工作值变得更加困难。为解决这一问题,定义了 EIEOS(电气空闲退出有序集),以提供低频序列。如图 16-11(第 739 页)所示,用于 8b/10b 编码的 EIEOS 通过重复使用 K28.7 控制字符,形成连续的 5 个 1 和 5 个 0 交替序列。这种低频信号能够产生更易被检测到的高电压信号。事实上,规范明确指出,该模式可确保接收器正确检测到电气空闲状态的退出——这是加扰数据无法实现的功能。EIEOS 需在以下条件下发送:
- 在进入 Configuration.Linkwidth.Start 或 Recovery.RcvrLock 状态后的第一个 TS1 之前。
- 在 Configuration.Linkwidth.Start、Recovery.RcvrLock 或 Recovery.RcvrCfg 状态下,每发送 32 个 TS1 或 TS2 之后。每当发送 EIEOS 或在 Recovery.RcvrCfg 状态下接收到第一个 TS2 时,TS1/TS2 计数将重置为零。
图 16-11:Gen1/Gen2 模式 EIEOS 符号模式
Gen3 模式。对于 8.0 GT/s 速率,同样需要 EIEOS,原因与 5.0 GT/s 相同。不过,此时有序集采用块的形式,如第 740 页图 16-12 所示。与之前一样,它在交替的 00h 和 FFh 字节中呈现低频模式,表现为重复的 8 个 0 后跟 8 个 1 的字符串。
此外,发送 EIEOS 是为了让处于 LTSSM 恢复状态的接收器能够建立块锁定,之后链路转换到 L0 状态。参见第 411 页的“块对齐”部分和第 438 页的“实现块对齐”部分。
在 Gen3 模式下,EIEOS 应在以下情况下发送:
- 在进入 Configuration.Linkwidth.Start 或 Recovery.RcvrLock 状态后,发送第一个 TS1 之前。
- 在数据流结束时,若未发送 EIOS 且 LTSSM 未进入 Recovery.RcvrLock 状态,则紧接在 EDS 帧标记之后立即执行。
- 每当发送 TS1 或 TS2 时,每 32 个 TS1/TS2
后执行。计数器在以下情况下重置为零时:
- 一个 EIEOS 被发送
- 在 Recovery.RcvrCfg 或 Configuration.Complete LTSSM 状态下接收到第一个 TS2 时
- 在均衡序列阶段 2 的下游端口,或阶段 3 的上行端口,会接收到两个设置了复位 EIEOS 间隔计数位的 TS1 序列。
- 在均衡序列期间,每经过 2^16 个 TS1 序列后,如果复位 EIEOS 间隔计数位阻止了 EIEOS 的发送,规范允许设计通过以下方式满足要求:在加扰 LFSR 与其种子值匹配后的 2 个 TS1 序列内发送一个 EIEOS。
- 作为 FTS 序列、合规模式或修改合规模式的一部分。
图 16-12:128b/130b EIEOS 块
16.5.1.3 接收器进入电气空闲状态(Receiver Entry to Electrical Idle)
当发送器进入电气空闲状态时,链路伙伴的接收器会根据数据速率做出响应,具体描述见以下章节。接收到 EIOS 通知接收器即将发生此状态,使其做好检测实际发生的准备。当接收器检测到此条件时,会关闭错误逻辑以防止因链路上不可靠活动导致的错误报告,并启动其电气空闲退出检测器,以便在发送器开始再次发送数据时恢复正常活动。电气空闲检测有两种选项:
检测电气空闲电压。一旦接收到 EIOS,预期发送器将很快停止传输。在 1.x 规范版本中,接收器通过观察输入电压是否降至有效信号阈值以下来检测此状态。这在 2.5 GT/s 时并不困难,但需要一个占用空间和功耗的静噪检测电路。
推断电气空闲。然而,在较高频率下,信号会逐渐衰减,使得静噪检测逻辑难以区分电平。对于 8.0 GT/s 而言尤其如此,因为接收器可能需要内部执行均衡以恢复良好信号。为解决这些检测问题,2.0 规范引入了允许接收器推断链路已进入电气空闲状态(而非测试电压电平)的概念。在此模型中,通过预期事件的缺失来指示链路未发送信号,因此可假定其处于电气空闲状态,如表 16-17 所列。举例说明,当链路处于 L0 状态时,流量控制更新应定期到达,而 SOS 信号也需按特定时序出现。为简化操作,允许接收器检查这些条件中的任一或全部。在链路训练期间,TS1 和 TS2 应定期到达,因此其缺失也可视为链路空闲的标志。 对于表格的最后两行,有可能根本没有接收到任何符号,这同样会被理解为链路处于空闲状态。由于电气空闲是针对整个链路而非独立通道发生的,因此无需每个通道单独测量这些时间。 相反,LTSSM 可以仅使用一个通用定时器来管理该链路上的所有通道。
表 16-17:电气空闲推断条件
| 状态 | 2.5 GT/s | 5.0 GT/s | 8.0 GT/s |
|---|---|---|---|
| L0 | 在 128 μs 窗口内未收到 FC Update 或 SOS | 在 128 μs 窗口内未收到 FC Update 或 SOS | 在 128 μs 窗口内未收到 FC Update 或 SOS |
| Recovery.RcvrCfg | 在 1280 UI 间隔内未收到 TS1 或 TS2 | 在 1280 UI 间隔内未收到 TS1 或 TS2 | 在 4 ms 窗口内未收到 TS1 或 TS2 |
| Recovery.Speed(successful_speed_negotiation = 1b) | 在 1280 UI 间隔内未收到 TS1 或 TS2 | 在 1280 UI 间隔内未收到 TS1 或 TS2 | 在 4680 UI 间隔内未收到 TS1 或 TS2 |
| Recovery.Speed(successful_speed_negotiation = 0b) | 在 2000 UI 间隔内未退出电气空闲 | 在 16000 UI 间隔内未退出电气空闲 | 在 16000 UI 间隔内未退出电气空闲 |
| Loopback.Active(作为从设备) | 在 128 μs 窗口内未退出电气空闲 | 不适用 | 不适用 |
接收器如何识别 EIOS 还取决于编码方案。对于 Gen1/Gen2 模式,当接收器检测到三个 IDL 符号中的两个时,即可识别出 EIOS。对于 Gen3 模式,当输入数据块的第 0-3 个符号与 EIOS 模式匹配时,即可识别出 EIOS。
16.5.1.4 接收器退出电气空闲状态(Receiver Exit from Electrical Idle)
接收器通过检测电压差来指示正常信令的恢复。当差分峰峰值电压超过电气空闲检测阈值时,将检测到电气空闲状态的退出,该阈值在所有数据速率下均可设置为 65 至 175 mV 之间。
在 2.5 GT/s 速率下无需额外操作,但在更高速率下,接收器仅在特定 LTSSM 状态期间接收 EIEOS 时,或在 5.0 GT/s 速率下传输 FTS 序列之前的四个 EIE 符号期间,才需依赖此检测电路。用于辅助检测电气空闲退出的 EIEOS 数量及时序取决于链路状态。更多详情请参见第 735 页的“主动状态电源管理(ASPM)“。
在电气空闲状态下,接收器的 PLL 会失去时钟同步。当发送器退出电气空闲状态时,会发送 FTS 以退出 L0s 状态,或发送 TS1/TS2 以退出所有其他链路状态。此举为 CDR 逻辑提供所需的跳变密度,使其能够重新同步接收器 PLL,从而实现位锁定和符号锁定或块对齐。
图 16-13 展示了链路状态转换,并重点标明了 L0、L0s 和 L1 之间的转换过程。需要注意的是,L0s 与 L1 之间不存在直接转换路径,因此在这两种状态之间切换时,链路必须先恢复到 L0 状态。
图 16-13:ASPM 链路状态转换
链路能力寄存器规定了设备对主动状态电源管理(ASPM)的支持情况。图 16-14 展示了该寄存器中的 ASPM 支持字段。在早期规范版本中,并非所有 4 个选项都可用,但 2.1 版规范已补全所有选项。请注意,第 22 位指示所有选项是否可用。
图 16-14:ASPM 支持
软件可通过链路控制寄存器中的主动状态电源管理控制字段启用或禁用 ASPM,如图 16-15(第 744 页)所示。可能的设置列于第 743 页的表 16-18 中。注意:规范建议,如果与 ASPM 相关的额外延迟超过等时事务的延迟限制,则应禁用用于等时事务路径中所有组件的 ASPM。
表 16-18:活动状态电源管理控制字段定义
| 设置 | 描述 |
|---|---|
| 00 b | 禁用 L0s 和 L1 ASPM |
| 01 b | 启用 L0s 并禁用 L1 |
表 16-18:活动状态电源管理控制字段定义(续)
| 设置 | 描述 |
|---|---|
| 10 b | 启用 L1,禁用 L0s |
| 11 b | 同时启用 L0s 和 L1 |
图 16-15:活动状态 PM 控制字段
16.5.2 L0s 状态(L0s State)
L0s 是一种链路电源状态,只能在硬件控制下进入,并应用于链路的单一方向。例如,在传统基于 PC 的系统中,大量流量源于功能向主系统内存发送数据。因此,上行通道承载着繁重流量,而下行通道可能承载极少流量。这些下行通道可在总线空闲时段进入 L0s 状态以节省功耗。
16.5.2.1 进入 L0s 状态(Entry into L0s)
发送器在检测到一段实现特定的空闲时间后,会启动从 L0 到 L0s 状态的转换。
进入 L0s 状态。该转换基于检测到链路空闲时间,针对链路的单一方向进行管理。端口在检测到不超过 的空闲时间后,必须进入 L0s 状态。
端点设备和交换机的空闲定义有所不同。其原因在于希望最小化恢复时间——因为链路恢复时间会通过交换机传播。例如,若交换机上游端口处于低功耗状态后检测到活动,这意味着一个 TLP 可能正在发往该交换机。该数据包需要路由到何处?它将发往某个下游端口,但与其等待接收数据包并确定目标端口后再唤醒它,最低延迟的做法是唤醒所有下游端口,这样最终成为目标的端口就能以最快速度就绪。
关于空闲时间的基本规则:
- 端点端口或根端口(Endpoint Port or Root
Port):
- 没有待传输的 TLP,或由于流控信用不足而暂时阻塞了它们的传输。
- 没有待传输的 DLLP。
- 上游交换机端口(Upstream Switch Port):
- 所有下游端口的接收通道已处于 L0s 状态。
- 无待传输的 TLP,或流控信用不足暂时阻止其传输。
- 无待传输的 DLLP。
- 下游交换机端口(Downstream Switch Port):
- 交换机上游端口的接收通道处于 L0s 状态。
- 没有待传输的 TLP,或流控制信用暂时不足导致其无法传输。
- 没有待传输的 DLLP。
事务层和数据链路层并不知晓物理层发射器是否已进入 L0s 状态,但触发进入 L0s 的空闲条件必须持续从事务层和链路层上报至物理层,以便其及时做出相关决策。需要注意的是,即使软件已禁用 ASPM,端口也必须始终容忍其接收器上的 L0s 状态。这使得链路另一端已启用 ASPM 的设备仍能将链路一侧切换至 L0s 状态。
必须交付流量控制信用额度。一种符合空闲条件的情况是:待处理的 TLP 因流量控制信用额度不足而被阻塞。当收到允许交付该待处理 TLP 的流量控制信用额度时,发送器口必须启动返回 L0 状态。此外,如果与处于 L0s 状态的发射器相关联的接收缓冲区释放出额外的流量控制信用额度,则发射器必须返回 L0 状态,并向相邻设备交付 FC_Update DLLP。 发送器启动进入 L0s 状态。当发送器检测到足够的空闲时间后,它会通过向接收器发送“电气空闲”有序集(EIOS)并停止传输,强制从 L0 状态转换到 L0s 状态。此时发送器和接收器均处于电气空闲状态,功耗降低。发送器与接收器之间的同步已丢失,恢复时需要重新进行训练。规范要求接收器中的 PLL 逻辑必须保持活动(供电)状态,以便能够从 L0s 快速恢复到 L0。
16.5.2.2 退出 L0s 状态(Exit from L0s State)
如果发送器检测到空闲条件不再成立,则必须启动从 L0s 到 L0 的退出过程。规范鼓励设计者监控能够提前指示 L0s 退出即将发生的事件,并启动恢复流程以加速返回 L0 状态的转换。例如,当端口的接收器收到一个非转发请求时,发送器知道很快会被要求发送一个完成响应。因此,发送器可以提前启动退出过程,以便在需要发送完成响应时链路状态已恢复为 L0。
发送器发起 L0s 退出。要退出 L0s 状态,发送器会发送一个或多个快速训练序列(FTS)有序集。链路伙伴接收器所需的数量已在之前的链路训练期间(训练过程中使用的 TS1 和 TS2 中的 N_FTS 字段)告知。在发送完指定数量的 FTS 后,会发送一个 SOS。接收器应能够建立位锁定和符号锁定或块锁定,并准备好恢复正常操作。
接收 L0s 退出的交换机采取的操作。如果一个端口接收到 L0s 到 L0 的转换序列,交换机可能还需要在其其他端口上发起 L0s 退出。考虑两种具体情况:
交换机下游端口接收 L0s 到 L0 转换。如果交换机当前处于 L0s 状态,则必须在其上游端口上发出 L0s 到 L0 的信号,因为从端点或下游交换机上来的数据包很可能需要向上游传输到根复合体。
切换上游端口接收从 L0s 到 L0 的转换。交换机必须立即在所有当前处于 L0s 状态的下游端口上发出 L0s 到 L0 的转换信号,因为它不希望等待数据包到达后才开始唤醒目标路径。
通过软件更改设备电源状态而进入 L1 状态的交换机端口不受 L0s 到 L0 转换的影响。然而,一旦上游链路完成到 L0 的转换,后续事务可能会针对该端口,从而引发从 L1 到 L0 的转换。
16.5.3 L1 ASPM 状态(L1 ASPM State)
可选的 L1 ASPM 状态比 L0s 提供更深的节能效果,但恢复延迟更大。该状态会导致链路双向进入 L1 状态,并导致每个设备内的链路层和事务层停用。
进入该状态由上游端口请求,例如来自端点或交换机的上游端口(上游端口如图 16-16 所示以阴影标识)。下游端口响应此请求,并通过与下游组件的协商过程,要么同意进入 L1 状态,要么拒绝该请求。退出 L1 ASPM 可由下游或上游端口发起。
图 16-16:仅上游端口发起 L1 ASPM
16.5.3.1 下游组件决定进入 L1 ASPM(Downstream Component Decides to Enter L1 ASPM)
规范并未精确定义端点或交换机上游端口决定尝试进入 L1 ASPM 状态的所有条件,但指出一种可能情况是:链路两侧均处于 L0s 状态且持续预设时间。给出的要求包括:
- 支持并启用 ASPM L1 入口
- 满足进入 L1 状态的设备特定要求
- 无待传输的 TLP
- 无待传输的 DLLP
- 如果下游组件是交换机,则该交换机的所有下游端口必须处于 L1 或更高节能状态后,上游端口才能启动 L1 进入流程。
16.5.3.2 进入 L1 ASPM 所需的协商(Negotiation Required to Enter L1 ASPM)
由于从 L1 ASPM 恢复所需的延迟较长,因此采用协商流程来确保链路另一端的端口已启用 L1 ASPM 并准备好进入该状态。该协商过程涉及发送多个数据包:
- PM_Active_State_Request_L1 DLLP——由下游端口发出以启动协商流程。
- PM_Request_Ack DLLP - 当上游端口满足进入 L1 ASPM 状态的所有要求时,由其返回。
- PM_Active_State_Nak 消息 TLP - 当上游端口无法进入 L1 ASPM 状态时,由其返回。
上游组件可能接受也可能不接受向 L1 ASPM 状态的转换。以下场景描述了导致这两种情况的各种情形。
16.5.3.3 场景 1:两个端口均准备进入 L1 ASPM 状态
第 750 页的图 16-17 总结了启用 L1 ASPM 状态转换所需的事件序列。该场景假设所有事务已在双向完成,且在协商期间未出现新的事务需求。
下游组件请求 L1 状态。若下游组件希望转换至 L1 状态,可在以下步骤完成后发送进入 L1 的请求:
- 事务层中的 TLP 调度被阻塞。
- 链路层已收到先前发送的最后一个 TLP 的确认,且重放缓冲区为空。
- 有足够的流控信用可用,以允许传输任何 FC 类型的最大可能数据包。这确保组件在退出 L1 状态后能够立即发出 TLP。
下游组件随后发送 PM_Active_State_Request_L1,以通知上游组件请求进入 L1 状态。该请求会重复发送,直到上游组件做出响应——要么是 PM_Request_ACK DLLP,要么是 PM_Active_State_NAK 消息。
上游组件对 L1 ASPM 请求的响应。下游端口(即上游组件中面向下方的端口)必须接受进入低功耗 L1 状态的请求,前提是满足以下所有条件:
- 该端口支持 ASPM L1 进入,并已启用此功能
- 无 TLP 计划传输
- 无 Ack 或 Nak DLLP 计划传输
上游组件确认进入 L1 的请求。上游组件发送 PM_Request_ACK,通知下游组件其同意在以下情况后进入 L1 ASPM 状态:
- 任何新 TLP 的块调度。
- 接收先前发送的最后一个 TLP 的确认(意味着其重放缓冲区为空)。
- 确保有足够的流控信用额度来发送任何 FC 类型的最大可能数据包,以便在退出 L1 状态后能立即发出 TLP。
上游组件随后持续发送 PM_Request_Ack,直到在其接收通道上检测到 EIOS,表明下游设备已进入电气空闲状态。
下游组件确认收到。当下游组件检测到 PM_Request_Ack 时,停止发送 PM_Active_State_Request_L1,禁用 DLLP 和 TLP 传输,发送 EIOS 并将其发送通道置于电气空闲状态。
上游组件接收电气空闲。当上游组件接收到 EIOS 时,停止发送 PM_Request_Ack DLLP, 禁用 DLLP 和 TLP 传输,发送 EIOS 并将其自身的发送通道置于电气空闲状态。
图 16-17:进入 L1 活动状态 PM 所需的协商序列
图中步骤:
设备阻止新的 TLP 调度
已接收最后 TLP 的 ACK(重试缓冲区为空)
所有 FC 信用额度足以发送最大尺寸的事务
持续发送 PM_Active_State_Request L1 请求,直至收到对端端口的 PM_Request_ACK 确认
收到 PM_Active_State_Request L1 请求
设备阻止新的 TLP 调度
已接收最后 TLP 的 ACK(重试缓冲区为空)
所有 FC 信用足够发送最大尺寸的事务
持续发送 PM_Request_ACK,直到接收到电气空闲有序集
PM_Request_ACK,导致 TLP 和 DLLP 数据包传输被禁用
发送电气空闲有序集,发送器进入电气空闲状态
收到电气空闲有序集,导致 TLP 和 DLLP 传输被禁用
发送通道进入电气空闲状态
16.5.3.4 场景 2:上游组件在接收 L1 请求前刚发送 TLP
该场景假设上游组件在收到下游设备进入 L1 状态的请求之前,刚被其核心逻辑指示向下游发送 TLP。若干协商规则定义了相关操作,以确保该情况得到正确处理。
下游组件必须接受 TLP。注意,当下游设备发送 PM_Active_State_L1 DLLP 后,必须等待上游组件的响应。在等待期间,下游组件必须能够接收来自上游设备的 TLP 和 DLLP。虽然它不会发送任何 TLP,但必须能够根据需要发送 DLLP,例如针对传入 TLP 的 ACK。在这种情况下,存在两种可能性:
- 返回 ACK 以确认 TLP 成功接收。
- 如果检测到 TLP 传输错误,则返回 NAK。在 L1 协商期间,允许对 TLP 进行重试。
上游组件收到进入 L1 的请求。规范要求上游组件立即接受或拒绝进入 L1 状态的请求。然而,规范进一步指出,在发送 PM_Request_ACK 之前,它必须:
- 新 TLP 的块调度
- 如有必要,等待先前发送的最后一个 TLP 的确认,并重试收到 NAK 的 TLP,除非发生链路确认超时条件。
一旦所有未完成的 TLP 均已确认,且所有其他条件均满足,上游设备必须返回一个 PM_Request_ACK DLLP。
16.5.3.5 场景 3:下游组件在协商期间接收 TLP
在协商序列期间,下游设备可能被指示向上游发送新的 TLP。然而,开始 L1 ASPM 协商过程的设备必须阻止新的 TLP 调度。这避免了进入 L1 状态与发送可能阻止进入 L1 的新 TLP 之间的竞争条件。因此,一旦下游设备已安排发送 PM_Request_L1,若收到 PM_Request_ACK,则必须完成向 L1 的转换。发送新的 TLP 必须等待进入 L1 状态之后,设备才能启动从 L1 返回 L0 的转换以发送该 TLP。
16.5.3.6 场景 4:上游组件在协商期间收到 TLP
如果上游组件在发送 PM_Request_Ack 后需要发送 TLP 或 DLLP,则必须首先完成向 L1 的转换。随后,它可以启动从 L1 到 L0 的状态变更以发送数据包。
16.5.3.7 场景 5:上游组件拒绝 L1 请求
第 752 页的图 16-18 总结了当上游组件拒绝进入 L1 ASPM 状态的请求时的协商序列。协商正常开始,下游组件请求 L1 状态。然而,上游设备返回一个 PM_Active_State_Nak TLP 以拒绝该请求。拒绝进入 L1 状态的原因包括:
- 不支持 L1 ASPM 或软件未启用此功能
- 有一个或多个 TLP 计划通过链路传输
- 计划传输 ACK 或 NAK DLLP
一旦拒绝消息被发送,上游组件可以根据需要继续发送 TLP 和 DLLP。拒绝告知下游组件当前无法进入 L1 状态,因此如果可能,它必须转而转换到 L0s 状态。
图 16-18:导致拒绝进入 L1 ASPM 状态的协商序列
16.5.3.8 退出 L1 ASPM 状态
任一组件在需要使用链路时,均可启动从 L1 状态返回 L0 状态的转换。无论哪种情况,其过程相同且无需任何协商。当退出 L1 状态涉及交换机时,规范要求:若其他交换机端口处于 ASPM 低功耗状态,且位于即将发送的数据包的可能路径上,则这些端口也必须转换至 L0 状态。这些问题将在后续章节中讨论。
L1 ASPM 退出信令。规范指出,退出 L1 状态通过退出电气空闲状态来触发,该过程始于发送 TS1 序列。接收器口通过向发起设备回发 TS1 序列作为响应,随后物理层遵循其 LTSSM 协议完成恢复状态,并将链路返回至 L0 状态。详情请参阅第 571 页的“恢复状态”部分。
交换机从下游组件接收 L1 退出信号。如图 16-19 所示,交换机必须通过回发 TS1 序列来响应下游端口的 L1 退出信号,并且在 (从 L1 退出下游信号开始计时)时间内,若其上游链路处于 L1 状态,则也必须退出该状态。
图 16-19:下游组件发出 L1 退出信号时的交换机行为
推测下游组件正在转换回 L0 状态的原因,是因为它准备向上游发送 TLP。由于 L1 退出延迟相对较长,交换机“不得等待其下游端口链路完全退出 L0 状态后,才在其上游端口链路上启动 L1 退出转换”。这可以防止因所有 L1 到 L0 转换按顺序进行而导致的累积延迟。
交换机从上游组件接收 L1 退出信号。在这种情况下,交换机必须向上游响应 TS1 序列,并且在 1 μs 内,还必须向所有处于 L1 ASPM 状态的下游端口发送 TS1 序列,使其返回 L0 状态。与前一示例相同,其目标是最大限度地减少
从发起者到事务目标路径上每个链路返回到 L0 状态的总退出延迟。第 755 页的图 16-20 总结了这些要求。交换机 F 与端点(EP)E 之间的链路处于 L1 状态,因为软件将 EP E 置于 D1 状态,导致该链路转换到 L1。只有处于 L1 ASPM 状态的链路会因根复合体(RC)发起退出 L1 ASPM 而转换到 L0。
图 16-20:上游组件发出 L1 退出信号时的交换机行为
16.5.4 ASPM 退出延迟(ASPM Exit Latency)
PCI Express 提供了相应机制,确保 L0s 和 L1 的 ASPM 退出延迟不超过设备的要求。所有设备都会报告其 L0s 和 L1 退出延迟,端点还会报告其在访问根复合体时能够容忍的总可接受延迟。该可接受延迟基于设备内部的数据缓冲区大小。如果位于端点和目标设备之间的设备链总延迟超过端点报告的可接受延迟,软件可以针对该端点禁用 ASPM。
设备报告的退出延迟会因链路两端设备是否共享同一参考时钟而有所不同。因此,链路状态寄存器中包含一个名为“插槽时钟“的位,用于指定组件使用的是平台提供的外部参考时钟,还是独立参考时钟(可能由内部生成)。软件会检查每条链路两端设备中的这些位,以确定它们是否都使用同一时钟并因此共享公共时钟。如果确实如此,软件会在两个设备中设置公共时钟位以报告此情况。第 757 页的图 16-21 展示了与管理 ASPM 退出延迟相关的寄存器及位域。
16.5.4.1 报告有效的 ASPM 退出延迟
由于时钟配置会影响设备将经历的退出延迟,设备必须通过链路状态寄存器中的“插槽时钟“状态位报告其参考时钟来源。该位由组件初始化以报告其参考时钟来源。若此位设置为 1,表示时钟使用平台生成的参考时钟;若清零(0),则表示使用独立时钟。
如果系统固件或软件确定链路两端组件均使用平台时钟,则两个设备内的参考时钟将处于同相状态。这将缩短从 L0s 和 L1 状态退出的延迟时间,并在链路控制寄存器的公共时钟字段中报告。组件必须随后更新其报告的退出延迟时间以反映正确值。请注意,如果时钟不同步,则默认值将保持正确,无需进一步操作。
L0s 退出延迟更新。L0s 的退出延迟基于默认假设(不存在公共时钟实现)在链路能力寄存器中报告。L0s 退出延迟也会在 TS1s 中报告。
在链路训练期间,该值用于指示退出 L0s 所需的 FTS 有序集数量(N_FTS)。如果软件随后检测到公共时钟实现,它将设置公共时钟字段,并向链路控制寄存器的重新训练链路位写入数据,以强制重复链路训练。在重新训练期间,将报告新的 N_FTS 值,并更新链路能力寄存器中的 L0s 延迟字段。
L1 退出延迟更新。链路重新训练后,新的数值也将报告在 L1 延迟字段中。
图 16-21:用于 ASPM 退出延迟管理与报告的配置寄存器
16.5.4.2 计算从端点到根复合体的延迟
第 759 页的图 16-22 展示了一个端点,其事务必须经过两个交换机才能到达根复合体。假设路径中的所有链路均处于 L1 状态,我们以端点 B 需要向主内存发送数据包为例进行说明。
- 首先,EP B 在时间 “T” 通过在其链路上发起 TS1 有序集来启动唤醒序列。EP B 的 L1 退出延迟最大为 8 μs,但 Switch C 的最大退出延迟为 16 μs。因此,该链路的退出延迟为 16 μs。
- 在检测到链路 B/C 上的 L1 退出后的 1 μs 内,Switch C 在 T+1 μs 时于链路 C/F 上发出 L1 退出信号。
- 链路 C/F 在 16 μs 内完成从 L1 的退出,时间为 T+17 μs。
- Switch F 在检测到来自 Switch C 的 L1 退出(T+2 μs)后的 1 μs 内,向根复合体发出从 L1 退出的信号。
- 链路 F/RC 在 8 μs 内完成从 L1 的退出,于 T+10 μs 完成。
- 将路径转换回目标 L0 状态的总延迟为 T+17 μs。
图 16-22:总 L1 延迟示例
16.6 软件发起的链路电源管理(Software Initiated Link Power Management)
当软件通过配置写入操作更改电源状态以实现节能时,设备必须通过将其链路转换为相应的低功耗状态来响应。
16.6.1 D1/D2/D3hot 与 L1 状态
规范要求,当设备内的所有功能均进入任意低功耗状态(D1、D2 或 D3hot)时,设备必须启动向 L1 状态的转换,如图 16-23 所示。设备通过软件发起配置访问或设备自身触发的事件返回 L0 状态。
图 16-23:当软件将设备电源级别从 D0 更改时,设备转换至 L1 状态
当设备接收到对 PMCSR 寄存器电源状态字段的配置写入时,会通过向上游组件发送 PM_Enter_L1 DLLP 来启动从 L0 到 L1 的状态转换。
16.6.1.1 进入 L1 状态(Entering the L1 State)
将链路置于 L1 状态的过程如图 16-24(第 762 页)所示。图中各步骤的详细说明如下:
一旦设备识别到其所有功能均处于 D2 状态,就必须准备将链路转换至 L1 状态。此过程首先需阻止新的 TLP 被调度。
来自下游端点的 TLP 可能在收到进入 D2 请求前尚未被确认。设备不得在未确认所有未完成的 TLP 之前响应链路电源状态变更请求。换言之,在进入 L1 状态前,重放缓冲区必须清空。
由于将链路恢复至活动状态涉及较长延迟,设备必须在返回活动状态后立即能够发送最大尺寸的 TLP。由于流控信用不足可能阻碍此操作,端点必须在进入 L1 前为每种流控类型预留足够的信用额度,以支持传输其支持的最大数据包。
当上述要求满足后,端点向上游设备发送 PM_Enter_L1 DLLP,指示上游组件将链路置入 L1 状态。该 PM_Enter_L1 消息将持续发送,直至收到上游设备返回的 PM_Request_ACK DLLP。
上游组件接收到 PM_Enter_L1 后,开始执行步骤 6、7、8 进行准备。此准备流程与下游组件在发出 L1 转换信号前执行的准备流程相同。
所有新的 TLP 调度被阻止。
若存在尚未确认的先前 TLP,上游设备将等待重放缓冲区中的所有事务均被确认后,再继续后续操作。
必须积累足够的流量控制信用,以确保每种流量控制类型都能传输最大的 TLP。
上游组件发送 PM_Request_ACK DLLP,以确认其已准备好进入 L1 状态。该 DLLP 会重复发送,直到接收到电气空闲有序集,表明已被接受。
当下游组件收到确认后,它会发送 EIOS,并将其发送通道置于电气空闲状态(发送器处于高阻态)。
上游组件识别到 EIOS 后,将其发送通道置于电气空闲状态。此时链路已进入 L1 状态。
图 16-24:链路从 L0 状态转换至 L1 状态所用流程
16.6.1.2 退出 L1 状态(Exiting the L1 State)
L1 状态的退出可由上游或下游组件发起,具体如下所述。本节还总结了用于退出 L1 状态的信号协议。
16.6.1.2.1 上游组件发起(Upstream Component Initiates)
软件可能需要使用当前处于低功耗状态的设备,这意味着电源管理软件必须发出配置写入命令,将其电源状态恢复至 D0。当配置请求准备从上游组件(根端口或交换机下游端口)发送时,该端口将退出电气空闲状态并启动重新训练,使链路恢复至
L0 状态。一旦链路处于活动状态,配置写入操作可被发送至设备,使其恢复到 D0 状态,此时设备即可正常使用。
16.6.1.2.2 下游组件发起 L1 到 L0 的转换(Downstream Component Initiates L1 to L0 Transition)
在 L1 状态下,参考时钟和电源仍会施加到链路上的设备上。这使得下游设备能够被设计为监控外部事件,并在事件发生时触发电源管理事件(PME)。在传统 PCI 中,这是通过边带 PME# 信号报告的,系统板逻辑通常利用该信号生成中断,通知 CPU 需要将设备恢复到完全工作状态。PCIe 取消了边带信号,转而通过带内消息来报告 PME(详见第 769 页的“PME 消息“部分)。
16.6.1.2.3 L1 退出协议(The L1 Exit Protocol)
在 L1 状态下,链路两个方向均处于电气空闲状态。设备通过退出电气空闲状态并发送 TS1 序列来发出 L1 退出信号。当链路对端检测到电气空闲状态退出时,会回传 TS1 序列。此序列将触发两端设备进入恢复状态,待该状态操作完成后,两端设备将返回 L0 状态。
16.6.2 L2/L3 就绪——移除链路电源(L2/L3 Ready — Removing Power from the Link)
一旦软件将设备内所有功能置于 状态,即可安全移除设备电源。此状态的典型应用场景是将系统中所有设备置于 D3hot 状态后统一断电,以实现最低功耗。但规范并未说明移除时钟和电源的具体机制,也未要求遵循特定操作顺序,从而允许多种实现方式。
如图 16-25(第 764 页)所示,设备为断电做准备的状态转换需经历以下步骤:先进入 L1 状态,再返回 L0 状态,最终到达 L2/L3 就绪状态。
图 16-25:与准备移除参考时钟和电源相关的链路状态转换
16.6.2.1 L2/L3 就绪握手序列(L2/L3 Ready Handshake Sequence)
规范要求在转换到 L2/L3 就绪状态时执行握手序列。这确保所有设备已准备好移除参考时钟和电源,同时避免在断电时意外丢失发送至根复合体的带内 PME 消息。
以下示例展示了从结构中的 PCIe 设备移除参考时钟和电源所需的握手序列。该示例假设系统级断电正在启动,但该序列同样适用于单个设备。具体步骤总结如下,并在第 766 页的图 16-26 中展示。整个序列分为 A 和 B 两部分表示,完整序列涉及的链路状态转换包括:
- L0 → L1(当软件将设备置于 D3 状态时)
- L1 → L0(当软件发起 PME_Turn_Off 消息时)
- L0 → L2/L3 就绪(由 PME_Turn_Off 握手序列完成导致,该序列以设备发送 PM_Enter_L23 DLLP 且链路进入电气空闲状态而结束)
以下步骤详细说明了第 766 页图 16-26 所示的序列。
电源管理软件首先将 PCIe 结构中的所有功能置于 D3 状态。
所有设备在进入 D3 状态时,将其链路转换至 L1 状态。
电源管理软件发起 PME_Turn_Off TLP 消息,该广播从所有根复合体端口发送至所有设备。此举可防止 PME 消息在电源移除时因上游传输中而丢失。需注意,该 TLP 的传递将导致每条链路重新切换至 L0 状态,以便向下游转发。
所有设备必须在 D3 状态下接收并确认 PME_Turn_Off 消息,通过返回 PME_TO_ACK TLP 消息进行响应。
交换机从其所有已启用的下游端口收集 PME_TO_ACK 消息,仅向上游根复合体转发一条汇聚后的 PME_TO_ACK 消息。这是因为这些消息的路由属性被设置为“收集并路由至根复合体“。
发送 PME_TO_ACK 后,当设备准备移除参考时钟和电源时,会持续发送 PM_Enter_L23 DLLP,直至收到 PM_Request_ACK DLLP。最后进入 L2/L3 就绪状态的链路,是连接至发起 PME_Turn_Off 消息的设备(本例中为根复合体)的链路。
当所有链路均已转换至 L2/L3 状态后,方可移除参考时钟和电源,但不得早于该状态转换后的 100 ns。若设备提供辅助电源(Vaux),链路将转换至 L2 状态;若无辅助电源可用,则链路处于 L3 状态。
图 16-26:进入 L2/L3 就绪状态的协商过程
16.6.2.2 退出 L2/L3 就绪状态 - 时钟与电源已移除(Exiting the L2/L3 Ready State — Clock and Power Removed)
如图 16-27 中的状态图所示,当电源断开时,设备退出 L2/L3 就绪状态,且仅有两种选择。当 Vaux 可用时,状态转换为 L2;否则转换为 L3。
链路状态转换通常由物理层的 LTSSM 控制。然而,转换为 L2 和 L3 状态是由于主电源断开所致,此时 LTSSM 已无法运行。因此,规范将 L2 和 L3 称为伪状态,用于解释设备在断电后的状态结果。
图 16-27:电源断开时从 L2/L3 就绪状态的状态转换
16.6.2.3 L2 状态(The L2 State)
某些设备被设计用于监控外部事件,并启动唤醒序列以恢复供电来处理这些事件。由于主电源已切断,这些设备需要像 这样的电源来监控事件并发出唤醒信号。
16.6.2.4 L3 状态(The L3 State)
在此状态下,设备完全断电,因此无法进行任何通信。从该状态恢复需要系统恢复供电和参考时钟。这会导致设备经历一次基础复位,之后需要通过软件初始化才能恢复正常运行。
16.7 链路唤醒协议与 PME 生成(Link Wake Protocol and PME Generation)
唤醒协议提供了一种方法,使端点能够重新激活上游链路,并请求软件将其恢复到 D0 状态,以便执行所需操作。PCIe 电源管理(PM)旨在与 PCI-PM 软件兼容,尽管实现方法有所不同。
PCIe 设备不使用边带信号,而是通过带内 PME 消息通知电源管理软件需要将设备恢复到 D0 状态。在任意低功耗状态下,设备可选择支持生成 PME 消息的能力。需注意,设备会报告其支持在哪些 PM 状态下发送 PME 消息。
PME 消息只能在链路处于 L0 状态时传递。重新激活链路所涉及的延迟取决于设备的 PM 状态和链路状态,但可能包括以下因素:
- 链路处于非通信(L2)状态 - 当链路处于 L2 状态时,由于参考时钟和主电源已被移除,因此无法进行通信。在时钟和电源恢复、执行基本复位并重新训练链路之前,无法发送 PME 消息。当设备发出唤醒信号时,将触发这些事件。这可能导致需要通信的设备与根复合体之间的路径上的所有链路被重新唤醒。
- 链路处于通信(L1)状态 - 当链路处于 L1 状态时,时钟和主电源仍处于活动状态;因此,设备只需退出 L1 状态,进入恢复状态重新训练链路,并将链路恢复至 L0 状态。一旦链路处于 L0 状态,即可传递 PME 消息。请注意,设备绝不会在 L2/L3 就绪状态下发送 PME 消息,因为进入该状态仅发生在 PME 通知已关闭之后,以准备移除时钟和电源。(参见第 764 页的“L2/L3 就绪握手序列“。)
- PME 已交付(L0 状态)—— 如果链路处于 L0 状态,设备会将 PME 消息传输至根复合体,通知电源管理软件该设备已检测到需要其恢复至 D0 状态的事件。请注意,该消息包含设备的请求者 ID(总线号、设备号和功能号),可快速告知软件哪个设备需要服务。
16.7.1 PME 消息(The PME Message)
PME 消息由支持 PME 通知的设备发送。消息格式如表 16-28(第 769 页)所示。该消息可由处于低功耗状态(D1、D2、D3 和 D3 )的设备发起,并在链路恢复至 L0 状态后立即发送。
图 16-28:PME 消息格式
PME 消息是一种具有以下特征的事务层数据包:
- TC 和 VC 均为零(不适用服务质量)
- 隐式路由至根复合体
- 作为已过账事务处理
- 不允许宽松排序,强制信号设备与根复合体之间的所有事务在 PME 消息之前传递到根复合体
16.7.2 PME 序列(The PME Sequence)
设备可在 PM 能力寄存器指定的任何低功耗状态下支持 PME。该寄存器还指定了设备在 状态下支持唤醒时所需的 电流。向软件发送 PME 的基本事件序列如下所述,前提是设备和系统已启用 PME 生成功能,且链路已转换至 L0 状态:
- 设备在其上游端口发出 PME 消息。
- PME 消息被隐式路由至根复合体。路径中的交换机在必要时将其上游端口转换至 L0 状态,并将数据包向上游转发。
- 根端口接收 PME 并将其转发至电源管理控制器。
- 控制器通常通过中断通知电源管理软件。软件利用消息中的请求者 ID 读取并清除 PMCSR 中的 PME_Status 位,使设备返回 D0 状态。根据电源节能程度的不同,PCI Express 驱动程序可能还需要恢复设备的配置寄存器。
- PM 软件也可能在设备因进入低功耗状态而丢失设备上下文时调用设备驱动程序。如果是这样,设备软件会恢复设备内的信息。
16.7.3 PME 消息背压死锁避免(PME Message Back Pressure Deadlock Avoidance)
16.7.3.1 背景
根复合体通常将接收到的 PME 消息存储在队列中,并调用 PM 软件处理每条消息。PME 会一直保留在该队列中,直到 PM 软件从请求设备的 PMCSR 寄存器中读取 PME_Status 位。一旦配置读取事务完成,该 PME 消息即可从内部队列中移除。
16.7.3.2 问题所在
若出现以下情况,则可能发生死锁:
- 传入的 PME 消息已填满 PME 消息队列,但同一根端口下游又发出了其他 PME 消息。
- PM 软件从 Root 发起配置读取请求,以读取最旧 PME 请求者的 PME_Status。
- 相应的拆分完成必须根据事务排序规则,将所有先前发布的 PME 消息推送到其前面。
- 由于队列已满,Root Complex 无法接受新的 PME 消息,因此路径暂时被阻塞。但这同时也意味着读取完成无法到达 Root Complex 以清除队列中的旧条目。
- 无法取得进展,从而发生死锁。
16.7.3.3 解决方案
如果根复合体始终接受新的 PME 消息(即使会导致队列溢出),则可避免该问题。在这种情况下,根复合体会直接丢弃后续的 PME 消息。为防止被丢弃的 PME 消息永久丢失,发送 PME 消息的设备需要测量一个称为 PME 服务超时的超时间隔。如果设备的 PME_Status 位未被 清除,则设备会假定其消息已丢失,并重新发送该消息。
16.7.4 PME 上下文(The PME Context)
生成 PME 的设备必须持续为用于检测、信号传输和处理 PME 事件的设备部分供电,这些部分统称为 PME 上下文。在 D3cold 状态下支持 PME 的设备会在主电源断开时使用辅助电源来维持 PME 上下文。通常属于 PME 上下文的项目包括:
PME_Status 位(必需)——当设备发送 PME 消息时设置,并由 PM 软件清除。支持 D3cold 状态下 PME 的设备必须将 PME_Status 位实现为“粘性”,即该值在基本复位后保持不变。
PME_Enable 位(必需)——该位必须保持置位,以继续启用功能生成 PME 消息和发出唤醒信号的能力。支持 D3cold 状态下 PME 的设备必须将 PME_Enable 实现为“粘性”,即该值在基本复位后保持不变。
设备特定状态信息——例如,在多种不同类型事件均可触发 PME 的情况下,设备可能会保留事件状态信息。
应用特定信息——例如,发起唤醒的调制解调器在支持的情况下会保留来电显示信息。
16.7.5 唤醒非通信链路(Waking Non-Communicating Links)
当支持 D3cold 状态下 PME 的设备需要发送 PME 消息时,必须首先将链路转换至 L0 状态。这一过程有时被称为唤醒。PCI Express 定义了两种触发非通信链路唤醒的方法:
- 信标(Beacon)——由辅助电源驱动的带内指示信号
- WAKE# 信号——由辅助电源驱动的边带信号
在这两种情况下,必须通知电源管理软件恢复主电源和参考时钟。这还会引发一次根本性复位,强制设备进入 D0 状态。一旦链路转换到 L0 状态,设备便会发送 PME 消息。由于重新激活链路需要复位,设备必须在上文所述的复位序列中保持 PME 上下文。
16.7.5.1 信标(Beacon)
这种信令机制设计为在辅助电源上运行,且功耗要求不高。信标本质上是一种通知上游组件的方式,告知其应通知软件处理唤醒请求。当交换机在下游端口接收到信标时,它们会相应地在自己的上行端口上发送信标。最终,信标到达根复合体,在那里产生一个中断,从而调用电源管理软件。
某些外形规格要求支持信标以实现系统唤醒,而其他规格则无此要求。规范要求符合外形规格标准,如果设备的外形规格不要求支持信标,则规范也不强制要求。然而,对于设计用于多种外形规格的“通用”组件,则要求支持信标。详情请参见第 483 页的“信标信令”。
16.7.5.2 WAKE
PCI Express 提供了一种名为 WAKE# 的边带信号,作为信标的替代方案,可直接路由至根复合体或其他系统逻辑,以通知电源管理软件。尽管希望尽量减少链路的引脚数量,但增加这个额外引脚的动机却很容易理解。原因在于,组件必须消耗辅助电源才能识别下游端口上的信标,并将其转发至上游端口。在电池供电系统中,辅助电源被严格保护,因为即使系统不执行任何任务,它也会消耗电池电量。在这种情况下,更优的解决方案是在传递唤醒通知时尽可能绕过更多组件,而 WAKE# 引脚恰好能很好地满足这一需求。另一方面,如果电源不是问题,那么 WAKE# 引脚可能就不那么理想了。
也可以采用混合实现方式。此时,WAKE# 信号被发送至交换机,交换机再通过其上行端口发送信标。相关选项如图 16-29(第 774 页 A 和 B)所示。请注意,当 WAKE# 信号被置位时,该信号将保持低电平状态,直至软件清除 PME_Status 位。
ATX 或基于 ATX 的连接器、卡以及迷你卡形态设备必须实现此信号。对于嵌入式设备,未规定必须使用 WAKE# 信号。
图 16-29:WAKE# 信号实现方式
16.7.6 辅助电源(Auxiliary Power)
在 D3cold 状态下支持 PME 的设备必须支持唤醒序列,并且根据 PCI-PM 规范允许消耗最大 375 mA 的辅助电流(否则仅允许 20 mA)。它们所需的电流量在 PM 能力寄存器的 Aux_Current 字段中报告。当 PMCSR 寄存器中的 PME_Enable 位被设置时,辅助电源即被启用。
PCI Express 将辅助电源的使用范围扩展到了 PCI-PM 规范的限制之外。现在,任何设备在通过设置设备控制寄存器的 Aux Power PM Enable 位(如图 16-30 所示,第 775 页)启用后,都可以消耗最大辅助电流。这使得设备能够在低功耗状态下支持其他功能,如 SM Bus。与 PCI-PM 规范相同,设备消耗的电流量在 PMC 寄存器的 Aux_Current 字段中报告。
图 16-30:不支持 PME 设备的辅助电流启用
16.8 提升 PM 效率(Improving PM Efficiency)
16.8.1 背景
随着处理器及其他系统组件获得更完善的电源管理机制,PCIe 组件等外设在 PC 系统中的功耗占比开始显著增加。早期 PCIe 版本虽支持部分软件与硬件电源管理,但协调系统级 PM 决策并非优先事项,导致软件可见性与控制能力十分有限。
这种协调缺失可能引发的问题在于:当系统进入休眠状态时,设备仍保持运行。此类设备可能发起中断或 DMA 流量,迫使系统唤醒以处理这些低优先级事件,从而违背节能目标。
系统可能无法知晓设备从请求系统服务(如内存读取)到获得响应之间能够等待多长时间。缺乏这一信息时,软件通常被迫假设响应时间必须始终最小化,因此电源管理策略无法留出足够的时间进行更多操作。然而,如果系统能够识别出不需要快速响应的时间窗口,它就可以更积极地实施电源管理,在更长时间内保持低功耗状态,而不会引发性能问题。2.1 规范修订版新增了两项特性来解决这些问题。
16.8.2 OBFF(优化缓冲区刷新与填充)
其中第一个机制是优化缓冲区刷新与填充,它提供了一种机制,使端点能够感知系统电源状态,从而确定与系统进行数据传输的最佳时机。
16.8.2.1 问题所在
具备总线主控能力的设备存在一个问题:如果它们不了解系统电源状态,可能会在更适合等待的时机发起事务。第 777 页图 16-31 中的示意图简单说明了这个问题:众多组件都在发起事件,导致系统空闲且可进入休眠状态的无活动时间既稀少又短暂。
相比之下,第 777 页图 16-32 展示了一种改进方案:将相同的事件分组并集中处理,使得系统足够空闲以进入休眠状态的时间既更频繁又更持久。显然,这将带来更好的节能效果,幸运的是,实现起来并不困难。PCIe 组件只需根据系统电源状态理解自身应执行的操作,并且需要一种方式来获知当前的状态。
图 16-31:系统空闲时间不足
图 16-32:改进的系统空闲时间
16.8.2.2 解决方案
OBFF 是一个可选提示,系统可利用它向组件告知最佳流量传输时间窗口。不过,这仅是一个提示,因此具备总线主控能力的设备仍可随时发起流量传输。当然,若设备如此操作,功耗将受到负面影响,因此应尽可能避免覆盖 OBFF 提示。该信息通过两种方式传递:向端点发送消息,或切换 WAKE# 引脚。若两种方式均可用,强烈建议使用引脚方式,因为这可避免使用额外功耗(可能跨越多个链路)来告知组件当前系统电源状态这一适得其反的步骤。实际上,仅当 WAKE# 引脚不可用时,才应使用 OBFF 消息。
第 778 页的图 16-33 展示了一个混合使用两种通信类型的示例。如果该引脚可用,则必须使用它,但在本例中,两个交换机之间无法选择该选项。为解决此问题,上层交换机可将 WAKE# 引脚接收到的状态转换为向下游发送的消息。此处需特别说明:强烈建议交换机将所有 OBFF 指示向下游转发,但并非强制要求。必要时(尤其是使用消息时),允许丢弃或合并部分指示。
图 16-33:OBFF 信令示例
使用 WAKE# 引脚。该引脚原本仅用于通知系统某个组件需要恢复供电,现被赋予额外含义——作为向 PCIe 组件传递系统电源状态的最简单且功耗最低的选项。该功能为可选,协议相当简单:通过 WAKE# 引脚的电平切换来传递系统状态。如第 779 页图 16-34 所示,存在多种状态转换,但仅有三种状态,具体描述如下:
- CPU 活跃 - 系统唤醒;所有事务正常。这是每个组件的初始状态。
- OBFF - 系统内存路径可用;与内存之间的传输正常,但其他事务应等待更高功耗状态。
- 空闲 - 在启动前等待更高状态。
图 16-34:WAKE# 引脚 OBFF 信号
当指示 CPU 活动或 OBFF 状态时,建议平台至少等待 10 μs 后再返回空闲状态,以便组件有足够时间发送在之前空闲状态期间可能已排队的报文。但由于该时间并非强制要求,因此也建议端点设备不要假设自己在 CPU 活动或 OBFF 窗口期内拥有固定的时间长度。同理,平台允许在实际进入空闲状态之前提前指示即将进入空闲状态 以便提前通知组件需要完成当前操作。这种提前通知机制专门用于避免以下情况:当端点设备恰好在平台进入空闲状态时开始传输,导致平台立即退出空闲状态。规范强烈建议,这应是提前指示空闲状态的唯一原因,且提前通知时间应尽可能短。
有趣的是,WAKE# 引脚仍可用于其原始用途,即允许组件唤醒系统,而这可能会让其他正在监控该引脚以获取 OBFF 信息的组件感到困惑,这并不意外。这可能导致电源或性能方面出现次优行为,但这种情况被认为是可恢复的,因此未采取任何措施加以防范。为涵盖所有这些情况,当信号不明确时,默认状态将为 CPU Active。
使用 OBFF 消息。如前所述,OBFF 信息可以通过消息进行通信,但建议仅在 WAKE# 引脚不可用时使用此方法。这些消息仅从根节点向下游传输。消息内容如图 16-35(第 781 页)所示,包括路由类型 100b(点对点)和一个 OBFF 代码,该代码提供以下值(所有其他代码均为保留):
- 1111b - CPU Active
- 0001b - OBFF
- 0000b - 空闲
如果接收到保留代码,组件必须将其视为“CPU 活跃”。如果端口接收到 OBFF 消息但不支持 OBFF 或尚未启用它,则必须将其视为不支持的请求(完成状态 UR)。
图 16-35:OBFF 消息内容
通过设备能力 2 寄存器(第 782 页图 16-36)指示对 OBFF 的支持,并使用设备控制 2 寄存器(第 783 页图 16-37)启用该功能。请注意,引脚和消息选项可能都可用。但引脚方法是首选,因为它是功耗更低的选项。
请注意,启用组件转发 OBFF 消息有两种变体,其区别在于如何处理目标链路不在 L0 状态的情况。在变体 A 中,仅当链路处于 L0 状态时才会发送消息。若链路不在 L0 状态,消息将被直接丢弃,以避免唤醒链路的开销。当下游端口所连接的设备无需时间关键型通信需求,且可通过将链路恢复至 L0 状态来表明其非紧急关注需求时,此变体为首选方案。对于变体 B,消息将始终被转发,且链路将恢复至 L0 状态。当下游设备能从平台状态的及时通知中获益时,此变体为首选方案。
图 16-36:OBFF 支持指示
使用 WAKE# 时,使能任意根端口声明该信号均被视为全局使能,除非存在多个 WAKE# 信号——此时仅影响与该端口关联的信号。使用 OBFF 消息时,使能某个根端口仅会启用该端口上的消息。规范中的预期是:若任一根端口被使能,通常所有根端口均应被使能,以确保整个平台处于使能状态。但允许选择性使能部分端口而其他端口保持禁用。
使能端口以支持 OBFF 时,规范建议先使能所有上游端口,再使能下游端口,最后使能根端口。对于未安装设备的热插拔插槽,此操作无法实现。针对该情况,允许通过插槽的 WAKE# 引脚使能 OBFF,但建议不使能插槽上方的下游端口来传递 OBFF 消息。
图 16-37:OBFF 使能寄存器
最后,让我们回顾一下第 778 页图 16-33 中的早期示例,以考虑这些寄存器在该场景下的可能取值。连接至下游交换机的交换机下游端口,其 OBFF 支持字段值应为 01b(仅消息模式),而其上行端口的值可能为 11b(两种模式均支持)。这些值可能被硬编码到设备中,或通过其他硬件初始化方式在复位后对软件可见。下游端口需将 OBFF 使能值设为 01b 或 10b(启用消息变体 A 或 B),以便发送 OBFF 消息。上行端口则应将 OBFF 使能值设为 11b(启用 WAKE# 信号)。规范指出,当交换机在不同端口间配置使用不同方法时,必须进行转换并转发指示信息。
16.8.3 LTR(延迟容忍度报告)(Latency Tolerance Reporting)
为提高 PM 效率而新增的第二个特性称为延迟容忍度报告(LTR)。这一可选功能允许设备在向平台请求服务时,报告其可容忍的延迟时间,从而使主内存等平台资源的 PM 策略能够将此纳入考量。若软件支持该功能,则可在设备需要时提供良好性能,而在无需快速响应时降低系统功耗。利用该信息的一种简单方式是:只要延迟容忍度仍能满足要求,系统便可推迟唤醒以响应服务请求。
规范中并未明确阐释“延迟容忍“的具体含义,但提及了一些可能相关的因素。例如,延迟容忍度可能影响可接受的性能表现,也可能决定组件能否正常运行。显然,这种差异将对 PM 策略的设计产生重大影响。同样地,设备可能通过缓冲或其他技术来补偿延迟敏感性,而软件若能获知这些信息将大有裨益。
16.8.3.1 LTR 寄存器(LTR Registers)
设备中的 LTR 能力通过 PCIe 设备能力 2 寄存器中的一个新位来发现(如图 16-38 所示,第 785 页),并在设备控制 2 寄存器中启用(如图 16-39 所示,第 785 页)。规范还规定了启用 LTR 的顺序:必须首先启用最靠近根节点的设备,然后依次向下到端点设备。除非其关联的根端口及所有中间交换机也支持 LTR 并已启用服务,否则端点设备不得启用。允许部分端点设备支持 LTR 而其他端点不支持。如果根端口或交换机下游端口接收到 LTR 消息但不支持或尚未启用,则该消息必须被视为不支持的请求。建议端点设备在启用后尽快发送 LTR 消息。强烈建议端点设备在任何 500 μs 周期内发送的 LTR 消息不超过两条,除非规范另有要求。但如果确实发送了更多消息,下游端口必须妥善处理,且不得因此生成错误。
图 16-38:LTR 能力状态
图 16-39:LTR 启用
LTR 信息的目标是根复合体。参与的下游设备都会报告各自的值,但端口仅使用所有通过该端口访问的设备所报告的最小值作为延迟限制。根复合体无需强制满足请求的服务延迟,但强烈建议予以满足。
16.8.3.2 LTR 消息(LTR Messages)
LTR 消息本身的格式如图 16-40(第 788 页)所示,其中路由类型为 100b(点对点),LTR 消息代码为 0001 0000b。报告两个延迟值:一个针对必须进行需要 Snoop 的的请求,另一个针对无需需要 Snoop 的(因此应更快完成)的请求。如图所示,两者的格式相同,包含以下字段:
- 延迟值与缩放因子——组合后可提供从 1 纳秒到约 34 s 范围内的值。将这些字段全部设置为零表示任何延迟都会影响设备,因此请求最佳服务。延迟的含义定义如下:
- 对于读取请求,延迟是指从发送请求 TLP 中的 END 符号开始,到收到该请求的第一个完成 TLP 中的 STP 符号为止的时间。
- 对于写入请求,延迟与流量控制反压相关。如果已发出一次写入,但由于缺乏流量控制信用额度而无法进行下一次写入,则延迟是指从该次写入的最后一个符号(END)到提供更多信用额度的 DLLP 的第一个符号(SDP)之间的时间。换言之,这代表了根端口应能接受下一次写入的时间范围。
- 需求位——可设置为无、仅一种类型或两种类型均设置,以指示该延迟值是否为必需。如果设备未实现这些流量类型之一,或对此没有服务要求,则必须清除关联字段对应的位。如果设备已报告要求,但随后被指示进入低于 D0 的设备电源状态,或其 LTR 使能位已被清除,则设备必须发送另一条 LTR 消息,报告这些延迟不再需要。
16.8.3.3 关于 LTR 使用的指南(Guidelines Regarding LTR Use)
端点在使用 LTR(延迟容忍度报告)时需遵循以下准则:
- 建议端点在每次服务需求发生变化时发送更新的 LTR 消息。规范对这类场景给出了示例,核心要点是:设备在调整服务需求时,必须将所有延迟因素纳入考量。这些因素包括参考时钟关闭后的恢复时间、链路重新建立到 L0 状态的时间、LTR 消息传输时间,以及平台为满足新需求所需的准备时间。
- 如果延迟容忍度正在降低,建议 LTR 消息的发送时间足够早于首个关联请求,以确保平台已做好相应准备。
- 如果延迟容忍度正在增加,则报告该变化的 LTR 消息应立即紧随使用先前延迟值的最后一个请求之后发送。
- 为达到最佳的整体平台能效,建议端点尽可能多地缓冲请求,然后以端点所能支持的最大长度进行突发传输。
多功能设备(MFD)有其自身的规则。例如,它们必须按如下方式发送“汇聚“LTR 消息:
- 报告的延迟值必须反映与任何功能相关联的最低值。需要 Snoop 的和不需要 Snoop 的延迟可能与不同的功能相关联,但如果没有任何功能对需要 Snoop 的或不需要 Snoop 的流量有要求,则不得设置该类型的需求位。
- 如果任何功能的值发生变化,从而影响汇聚值,MFD 必须向上游发送新的 LTR 消息。
交换机有一组与 LTR 相关的类似规则。基本上,它们从已启用 LTR 的下游端口收集消息,并根据以下规则向上游发送“汇聚“消息:
- 如果交换机支持 LTR,则必须在其所有端口上支持该功能。
- 仅当 LTR 启用位被设置时,或软件清除该位后不久(以便报告之前的任何要求不再有效),上游端口才允许发送 LTR 消息。
- 汇聚后的 LTR 值基于所有参与的下游端口报告的最低值。如果需求位被清除,或报告了无效值,则延迟被视为无限大。
- 如果任何下游端口报告需要 LTR 值,则在上游转发的 LTR 消息中,该类型的需求位将被置位。
- 向上游报告的 LTR 值必须考虑交换机本身的延迟。如果交换机的延迟因其运行模式而改变,则不得超过所有下游端口报告的最小值的 20%。上游端口报告的值是所有下游端口报告的最小值减去交换机自身的延迟,但该值不能小于零。
- 如果下游端口进入 DL_Down 状态,则该端口之前的延迟必须被视为无效。如果这改变了上游的汇聚值,则必须发送新消息来报告该变化。
- 如果某个下游端口的 LTR 使能位被清除,则与该端口相关的任何延迟必须视为无效,这可能导致新的 LTR 消息被发送到上游。
- 如果任何下游端口接收到会改变汇聚值的新 LTR 值,交换机必须向上游发送新的 LTR 消息以报告该变化。
最后,根复合体也有几条与 LTR 相关的规则:
- 只要满足服务要求,RC 允许延迟处理设备请求。此规则的一个应用场景可能是将来自某个端点的多个请求缓冲起来,并批量处理它们。
- 如果在一系列请求进行过程中更新了延迟要求,RC 必须在处理下一个请求之前理解新值,且所用时间需短于先前报告的延迟要求。
图 16-40:LTR 消息格式
16.8.3.4 LTR 示例
为说明目前讨论的概念,请考虑图 16-41(第 789 页)所示的示例拓扑结构。在此结构中,左下角的端点已向交换机发送了一条 LTR 消息,报告其需要 Snoop 的延迟要求为 1200 ns。此时,连接到该交换机的其他端点均未报告 LTR 值,因此该值成为需向上游报告的汇聚值。然而,交换机内部存在 50 ns 的延迟,因此必须从报告值中减去该延迟,导致上游端口向根端口发送一条 LTR 消息,报告值为 1150 ns。
图 16-41:LTR 示例
接下来,传统端点发送一条延迟要求为 5000 纳秒的 LTR 消息,如图 16-42(第 790 页)所示。由于该值大于当前交换机的汇聚值,因此在这种情况下不会发送 LTR 消息。
图 16-42:LTR - 发生变化但未更新
在下一阶段,中间端点报告其 LTR 值为 700 ns。该值小于当前汇聚值,因此交换机通过减去其内部延迟计算出新值 650 ns,并将其作为 LTR 消息向上游转发。这使得该根端口的当前延迟要求变为 650 ns,如图 16-43(第 791 页)所示。
最终,中间端点(Endpoint)的链路因某种原因停止工作,如图 16-44(第 791 页)所示,交换机端口(Switch Port)报告 DL_Down。因此,该端口的 LTR 值必须被视为无效。由于该值此前被用作当前汇聚值,汇聚值将更新为仍然有效的最低值,即最左侧端点报告的 1200 ns。随后,交换机将减去其内部延迟,并通过新的 LTR 消息向根端口(Root Port)报告 1150 ns。
图 16-43:LTR - 随更新变化
图 16-44:LTR - 链路断开情况